Find your system's export
In module 2.2, the bridge read runtime/exemplos/agenda.csv e runtime/exemplos/erp-vendas.csv. These files imitate what a system without an API provides: a export.
The first step is to find this file on your system. Look in the menus for “Export,” “Reports,” or “Save as CSV.” In Sônia’s client’s ERP, it’s the monthly sales report, saved in a fixed folder.
🆕 New here? Three words from this module
- Export — the file the system generates so you can take data out of it (CSV, spreadsheet).
- Header — the first line of the CSV, with the name of each column. The bridge uses these names to find the values.
- Environment variable — a named value (such as
PONTE_DADOS) that a program reads when it starts. It lets you change the configuration without touching the code.
How to read the diagram: the blue arrows always go from left to right. The system generates the file, the file lands in a folder, and the bridge (highlighted box) reads that folder. Nothing goes back to the ERP: that’s what keeps the risk low.
✓ Export format the bridge can read easily
- ✓ First line with the column names
- ✓ Comma-separated columns, like the kit examples
- ✓ Always saves to the same folder, with the same name
- ✓ Numbers with a decimal point (
18.50)
✗ Export that requires adjustment
- ✗ Semicolon-separated (common in Brazilian spreadsheets)
- ✗ Values with commas inside a field
- ✗ Title or total rows before the header
- ✗ File name that changes every day
💡 Why the right-hand column matters
The sample bridge separates columns by splitting each line at commas. If your file uses semicolons or has a comma inside a name, the data is read incorrectly. It’s not a defect: it’s a simple model. In topic 3, you ask the agent to adjust it.
the file that comes out of the system
column names
same place, same name
from the system to the agent
Point the bridge to your files
The bridge doesn’t have the file paths set in stone. Right at the beginning of the server.mjs it asks: is there PONTE_DADOS? If it exists, read from there. If not, use the folder runtime/exemplos/.
This is the actual line from the kit file:
const pastaExemplos = process.env.PONTE_DADOS || join(dirname(fileURLToPath(import.meta.url)), '..', '..', 'exemplos');
function lerCsv(nome) {
const [cabecalho, ...linhas] = readFileSync(join(pastaExemplos, nome), 'utf8').trim().split('\n');
const campos = cabecalho.split(',');
return linhas.map(l => Object.fromEntries(l.split(',').map((v, i) => [campos[i], v])));
}
|| means "otherwise." And the function lerCsv combine the folder with the name from the file (agenda.csv, erp-vendas.csv). Either your export has that name, or you change the name in the code (topic 3).Recipe R3 says to put the variable in the .mcp.json, in the field env. This way, every time Claude Code connects the bridge, it starts up already pointed at your folder.
Edit the .mcp.json from the kit's root. Today it has only command e args; add the field env with your folder path:
{
"mcpServers": {
"ponte-modelo": {
"command": "node",
"args": ["runtime/pontes/mcp-modelo/server.mjs"],
"env": { "PONTE_DADOS": "/caminho/da/exportacao" }
}
}
}
Close the claude, open it again in the kit folder and check that the bridge is still connected:
claude mcp list
Real output (10/05/2026, Linux), bridge line:
ponte-modelo: node runtime/pontes/mcp-modelo/server.mjs - ✔ Connected
✔ Connected. Replace /caminho/da/exportacao using the full path to your folder, in quotes, with no trailing slash.| Situation | Where the bridge reads from |
|---|---|
Without PONTE_DADOS | runtime/exemplos/ (a made-up Clara and Sônia) |
With PONTE_DADOS no env of the .mcp.json | the folder you wrote there |
Running --selftest directly in the terminal | the examples (the .mcp.json only applies when the agent connects the bridge) |
What to look for in the table: the last line avoids confusion. The --selftest continues proving the model with the examples; the bridge connected by the agent is what reads your folder.
💡 Don't rename the bridge for now
O .claude/settings.json from the kit enables the bridge by name, in "enabledMcpjsonServers": ["ponte-modelo"]. If you change the name in .mcp.json, change it there too, or Claude Code will ask for approval again.
switches the folder being read
env field
hard-coded
claude mcp list
Change the columns with the agent’s help
Each bridge tool has a purpose run(): that’s where the calculation happens. And that’s where the example CSV column names are. This is the run() actual tool resumo_vendas:
run({ agrupar_por = 'cliente' } = {}) {
const grupos = {};
let total = 0;
for (const r of lerCsv('erp-vendas.csv')) {
const v = Number(r.quantidade) * Number(r.valor_unitario);
grupos[r[agrupar_por]] = (grupos[r[agrupar_por]] || 0) + v;
total += v;
}
const linhas = Object.entries(grupos).map(([k, v]) => `${k}: R$ ${v.toFixed(2)}`);
return [...linhas, `TOTAL: R$ ${total.toFixed(2)}`].join('\n');
},
r.quantidade e r.valor_unitario are example header column names (data,cliente,produto,quantidade,valor_unitario). If your ERP calls it something else, that’s the only thing that changes.How to read the diagram: on the left, an invented header from some ERP; on the right, the names the code expects. The two lit arrows are the ones used in the calculation. Changing the name in the code connects the right arrow: the rule (quantity times price) doesn’t change.
You don't need to edit the code by hand. Ask the agent, with a written limit: only replace names inside the run(), without creating a tool that writes.
Open claude in the kit folder and paste (replace what’s between < >):
Leia runtime/pontes/mcp-modelo/server.mjs e a primeira linha do meu arquivo </caminho/da/exportacao/vendas.csv>. Na ferramenta resumo_vendas, troque só os nomes de colunas usados em run() e o nome do arquivo em lerCsv pelos do meu arquivo. Se o meu arquivo usar ponto e vírgula, ajuste a separação em lerCsv. Não crie ferramenta que escreve e não mexa em listar_horarios_livres. Antes de salvar, me mostre o antes e o depois de cada linha alterada.
run() and of lerCsv changing. If a new tool or any file writing appears, decline and ask again.💡 Save the old proof before making changes
Run the --selftest once before the switch and note the TOTAL: R$ 856.00. After the change, the selftest keeps reading the examples, which have the old names, so its total is no longer valid. The test is now the calculation by hand with your data (topic 5).
where the account is calculated
what you replace
what stays the same
you check
Keep the bridge read-only
The server.mjs brings the rule in a comment: "POLITICA: both tools only READ (N4). A tool that writes needs another level and confirmation."
Reading is N4: the agent does it on its own, without notifying you, because nothing changes in the world. The temptation appears right away. Clara will want the agent to mark consult, not just list the time. That already counts as writing, and recipe R3 is clear: a tool that writes is raised to "modify" in POLITICA.md, N2, asks first.
✓ Read-only tool (N4)
- ✓
listar_horarios_livres: shows what's available - ✓
resumo_vendas: sums and groups - ✓ A mistake here costs you a wrong answer, not corrupted data
- ✓ The agent uses it without asking
✗ Tool that writes (moves up to N2)
- ✗ Schedule a patient for an appointment slot
- ✗ Record or correct a sale in the ERP file
- ✗ A mistake here corrupts data that others use
- ✗ Only with a request and “yes” each time
Start with read-only access
Use the bridge for a few weeks just to look things up. You'll learn where it makes mistakes without taking any risks.
If you need to write, change the level first
Before the code, the line in the CAPACIDADES.md now says "change (N2)", as in the agenda example included in the file.
Separate writing tool
Never turn a read-only tool into one that "reads and writes." A new one, with a name that says what it does, makes it clear when the agent will ask.
⚠️ Read what the agent wrote in the bridge
When the agent changes the server.mjs, it changes the program that will run every time you ask for something. Look for words like in the before and after writeFileSync or appendFileSync: they write to a file. In a read-only bridge, only readFileSync should appear.
on its own, without notice
asks each time
one name, one action
the only one that reads without writing
Check Sônia’s summary by hand
A new bridge only counts after a calculation you did yourself. Not because the code makes lots of mistakes, but because a misspelled column name doesn't cause an error: it gives you a wrong number that looks right.
Practice with Sônia's data, which you know. Run the selftest and recalculate the total with a calculator.
In the terminal, from inside the kit folder:
node runtime/pontes/mcp-modelo/server.mjs --selftest
Real output (10/05/2026, Linux):
tools: 2 (listar_horarios_livres, resumo_vendas) 2026-10-06 09:00 · Dra. Ana 2026-10-06 10:00 · Dra. Ana 2026-10-06 15:00 · Dr. Bruno TOTAL: R$ 856.00
TOTAL: R$ 856.00. Now close the terminal and calculate the table below.| erp-vendas.csv line | Account | Value |
|---|---|---|
| 01/10 · Mercado Sol · Coffee 500g | 10 × 18,50 | 185,00 |
| 01/10 · Padaria Lua · Sugar 1kg | 25 × 5,20 | 130,00 |
| 02/10 · Mercado Sol · Sugar 1kg | 40 × 5,20 | 208,00 |
| 03/10 · Empório Mar · Coffee 500g | 6 × 18,50 | 111,00 |
| 03/10 · Padaria Lua · Coffee 500g | 12 × 18,50 | 222,00 |
| Total | 185 + 130 + 208 + 111 + 222 | 856,00 |
What to look for in the table: by client, the same account shows Mercado Sol 393.00 (185 + 208), Padaria Lua 352.00 (130 + 222), and Empório Mar 111.00. Adding the three gives 856.00 again. When the bridge reads the real data, do the same with three or four rows you can add up.
Open claude in the kit folder and paste:
Use a tool resumo_vendas da ponte-modelo agrupando por cliente. Mostre a resposta da ferramenta sem arredondar e sem comentar.
💡 The calculation you check by hand becomes your proof
Write down: "file from a given date, client X, amount Y". That’s proof in the kit’s format, command → expected output. In module 3.4, it goes into the goal and is checked automatically.
three lines are enough
Sônia's total
wrong number without an error
command → output
Register the bridge in CAPACIDADES.md
The rule in runtime/CAPACIDADES.md applies here: a system without a line isn’t used by the agent. The bridge goes on the map only after you have the numbers in hand, along with the test date.
The file already includes an example for Sônia's case, marked as pending:
| ERP sem API | Exportação CSV diária | 6 | ler ~/erp/export/*.csv | ler (N4) | pendente |
After verifying the account, Sônia’s line looks like this (replace it with your test data):
| ERP da distribuidora | Exportação CSV + ponte MCP | 6 | tool resumo_vendas da ponte-modelo | ler (N4) | <AAAA-MM-DD> ok |
pendente by the date with ok.Open claude in the kit folder and paste:
Acrescente uma linha na tabela de runtime/CAPACIDADES.md para a ponte-modelo lendo a minha exportação: via ponte local por MCP, nível 6, política ler (N4), testado em <data de hoje> ok. Não mude as outras linhas. Mostre a linha antes de salvar.
runtime/CAPACIDADES.md and see the new row in the main table, with all six columns filled in.How to read the diagram: the first three steps are technical; the fourth (highlighted) is what enables use. Skipping a line on the map leaves the agent using a system no one has registered.
Quick test (optional): you pointed the bridge to the ERP export and changed the columns. What authorizes the agent to use the bridge day to day?
no line, no usage
pending becomes OK
how the agent calls it
the row policy
🎓 Module summary
Next module:
2.4 — Browser with policy