com. editalmd/ editalmd
by editalmd.com · remote · no sign-in to list tools · v1.0.1 · published by com.editalmd
Brazilian public procurement (PNCP): search, deadlines, tender markdown, alerts and watches.
59 tools: 7 can delete or cancel things, 1 do something that can't be undone, 30 change things and 21 only read.
Scanned Oct 21, 2026
- Deletes or cancels7Claude Code: deny: see these tools
- Can't be undone1Claude Code: ask: see these tools
- Changes things30Claude Code: ask: see these tools
- Only reads21Claude Code: allow: see these tools
16 checks matched something in the tool definitions. No finding is not a safety guarantee. How the checks work.
claude mcp add --transport http editalmd https://editalmd.com/mcpFindings
Matches of fixed checks, with the text they matched.
- Warnpreview_alert
The server marks "preview_alert" as not read-only (readOnlyHint: false), and its words say it reads.
What this check looks forMatched text
annotations: {"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":false}; The name "preview_alert" says "preview": a word for reading.
The server marks "open_tenders_in_field" read-only (readOnlyHint: true), and its own name, description or input give the class "write".
What this check looks forMatched text
annotations: {"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}; The name "open_tenders_in_field" says "open": a word for a change.
The server marks "get_qualification" as not read-only (readOnlyHint: false), and its words say it reads.
What this check looks forMatched text
annotations: {"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":false}; The name "get_qualification" says "get": a word for reading.
- Infoevaluation_quota
The input schema at properties.agent_pass.description mentions "credential".
What this check looks forMatched text
inputSchema.properties.agent_pass.description: "Persistent individual credential from POST https://api.editalmd.com/lici..."
The description mentions "credential".
What this check looks forMatched text
description: "...returns the same access. Allowance per credential, until the earlier date of the agent's..."
The input schema at properties.agent_pass.description mentions "credential".
What this check looks forMatched text
inputSchema.properties.agent_pass.description: "Persistent individual credential from POST https://api.editalmd.com/lici..."
Show 10 more findingsShow fewer
- Infoevaluation_basic
The description mentions "credential".
What this check looks forMatched text
description: "...It does not open premium. Allowance per credential, until the earlier date of the agent's..."
- Infoevaluation_basic
The input schema at properties.agent_pass.description mentions "credential".
What this check looks forMatched text
inputSchema.properties.agent_pass.description: "Persistent individual credential from POST https://api.editalmd.com/lici..."
The description mentions "credential".
What this check looks forMatched text
description: "...h the hash of the source. Allowance per credential, until the earlier date of the agent's..."
The input schema at properties.agent_pass.description mentions "credential".
What this check looks forMatched text
inputSchema.properties.agent_pass.description: "Persistent individual credential from POST https://api.editalmd.com/lici..."
The input schema at properties.agent_pass.description mentions "credential".
What this check looks forMatched text
inputSchema.properties.agent_pass.description: "Individual agent credential, required together with X-Editalmd-Aval..."
The input schema at properties.agent_pass.description mentions "credential".
What this check looks forMatched text
inputSchema.properties.agent_pass.description: "Individual agent credential, required together with X-Editalmd-Aval..."
The input schema at properties.agent_pass.description mentions "credential".
What this check looks forMatched text
inputSchema.properties.agent_pass.description: "Individual agent credential, required together with X-Editalmd-Aval..."
The input schema at properties.agent_pass.description mentions "credential".
What this check looks forMatched text
inputSchema.properties.agent_pass.description: "Individual agent credential, required together with X-Editalmd-Aval..."
The input schema at properties.agent_pass.description mentions "credential".
What this check looks forMatched text
inputSchema.properties.agent_pass.description: "Individual agent credential, required together with X-Editalmd-Aval..."
The input schema at properties.agent_pass.description mentions "credential".
What this check looks forMatched text
inputSchema.properties.agent_pass.description: "Individual agent credential, required together with X-Editalmd-Aval..."
Tools
Open a tool for its reasons and full description. Descriptions are the publisher's own words, shown as they are.
59 tools
Deletes or cancels 7Claude Code: deny
add_companyImports the CNPJ into a new organization or into the organization of the organization key.No findings
Why it is in this group
- The name "add_company" says "add": a word for a change.
- The server marks it destructive (destructiveHint: true).
Description, as the server wrote it Imports the CNPJ into a new organization or into the organization of the organization key. Without X-Organization-Id, it creates the organization with the company name and EditalMD on, or returns the one that the person removed from the list (201). With X-Organization-Id or an organization key, the record goes to that organization if the caller manages it and it has no company. Returns 200 when the CNPJ is already in an organization of the caller. Up to 100 companies; no partners or contacts; no analysis starts.
Annotations the server declares
- title: Add a company
- readOnlyHint: false
- destructiveHint: true
- idempotentHint: true
- openWorldHint: false
remove_companyRemoves the company from the list (owner or admin); the organization and the PDFs stay, and adding the CNPJ again brings it back.No findings
Why it is in this group
- The name "remove_company" says "remove": a word for removing or ending something.
- The server marks it destructive (destructiveHint: true).
Description, as the server wrote it Removes the company from the list (owner or admin); the organization and the PDFs stay, and adding the CNPJ again brings it back.
Annotations the server declares
- title: Remove a company
- readOnlyHint: false
- destructiveHint: true
- idempotentHint: true
- openWorldHint: false
remove_company_documentRemoves a proof from your own company; the analyses that used it become out of date.No findings
Why it is in this group
- The name "remove_company_document" says "remove": a word for removing or ending something.
- The server marks it destructive (destructiveHint: true).
Description, as the server wrote it Removes a proof from your own company; the analyses that used it become out of date.
Annotations the server declares
- title: Remove a company document
- readOnlyHint: false
- destructiveHint: true
- idempotentHint: true
- openWorldHint: false
remove_savedRemoves the procurement from the personal list of the owner.No findings
Why it is in this group
- The name "remove_saved" says "remove": a word for removing or ending something.
- The server marks it destructive (destructiveHint: true).
Description, as the server wrote it Removes the procurement from the personal list of the owner. Saving does not create a watch or a notification. The client sends only the ID; the snapshot comes from the collection.
Annotations the server declares
- title: Remove a saved procurement
- readOnlyHint: false
- destructiveHint: true
- idempotentHint: true
- openWorldHint: false
save_procurementSaves the procurement, up to 200 per owner.No findings
Why it is in this group
- The name "save_procurement" says "save": a word for a change.
- The server marks it destructive (destructiveHint: true).
Description, as the server wrote it Saves the procurement, up to 200 per owner. Saving does not create a watch or a notification. The client sends only the ID; the snapshot comes from the collection.
Annotations the server declares
- title: Save a procurement
- readOnlyHint: false
- destructiveHint: true
- idempotentHint: true
- openWorldHint: false
select_companySelects a registered company; it does not run an analysis.No findings
Why it is in this group
- The name "select_company" says "select": a word for a change.
- The server marks it destructive (destructiveHint: true).
Description, as the server wrote it Selects a registered company; it does not run an analysis. Each person's choice is kept in the account. Repeating the current choice writes nothing.
Annotations the server declares
- title: Select a company
- readOnlyHint: false
- destructiveHint: true
- idempotentHint: true
- openWorldHint: false
update_alertEdits the interest, or pauses or turns on again an alert of the owner.No findings
Why it is in this group
- The name "update_alert" says "update": a word for a change.
- The server marks it destructive (destructiveHint: true).
Description, as the server wrote it Edits the interest, or pauses or turns on again an alert of the owner. The filters replace the whole filter.
Annotations the server declares
- title: Edit an alert
- readOnlyHint: false
- destructiveHint: true
- idempotentHint: false
- openWorldHint: true
Can't be undone 1Claude Code: ask
attach_company_documentSends a PDF proof of the company.No findings
Why it is in this group
- The name "attach_company_document" says "attach": a word for a change.
- The description's first verb is "send": a word for sending, and what is sent cannot be taken back.
Description, as the server wrote it Sends a PDF proof of the company. It does not start OCR. Requires a session; for large files, prefer HTTP. Returns 201. JSON up to 11,200,000 bytes; PDF up to 8 MiB; 20 documents, 80 MiB and 50 pages per company. An identical file is reused. The automatic reading happens only when you request the analysis.
Annotations the server declares
- title: Attach a company document
- readOnlyHint: false
- destructiveHint: false
- idempotentHint: false
- openWorldHint: false
Changes things 30Claude Code: ask
account_trackingChecks that the Salvas, Alertas and Vigias belong to the account of the session.No findings
Why it is in this group
- Nothing in its name or description says what it does, so it is counted as a write.
- The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.
Description, as the server wrote it Checks that the Salvas, Alertas and Vigias belong to the account of the session. The lists of a guest edm_… move to the account with `POST /api/auth/claim`; a POST to this route answers 410 with the path.
Annotations the server declares
- title: Account follow-up lists
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
analyze_participationStarts or resumes the analysis with the company record, the attachments and the tender.No findings
Why it is in this group
- The name "analyze_participation" says "analyze": a word for reading.
- The description's first verb is "start": a word for a change.
Description, as the server wrote it Starts or resumes the analysis with the company record, the attachments and the tender. Call it only when the user asks; follow it with get_participation. Returns 202 after it accepts and keeps the request, and 200 when it reuses a finished analysis. It uses the profile and the attachments of this owner. Interrupted requests can resume; failures tell the reason and the next action. An explicit POST resumes a pause. Up to 2 thousand facts and 100 tenders per company, subject to the available capacity and budget. Follow-up only by GET. The analysis is a triage with evidence, not a final qualification decision or an external legal opinion.
Annotations the server declares
- title: Analyze participation
- readOnlyHint: false
- destructiveHint: false
- idempotentHint: false
- openWorldHint: false
api_indexThe EditalMD API index, with the routes.No findings
Why it is in this group
- Nothing in its name or description says what it does, so it is counted as a write.
- The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.
Description, as the server wrote it The EditalMD API index, with the routes.
Annotations the server declares
- title: API index
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
awarded_pricesAwarded results for a similar item, as a free summary: how many results, the median and the range (p25/p75) of the same catalog product in the same unit, without the extremes; the …No findings
Why it is in this group
- Nothing in its name or description says what it does, so it is counted as a write.
- The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.
Description, as the server wrote it Awarded results for a similar item, as a free summary: how many results, the median and the range (p25/p75) of the same catalog product in the same unit, without the extremes; the volume bought; the value for your quantity; and the other groups that the search found (ask for the product and the unit of one of them to switch). It searches awarded results by item description. It also accepts POST, PUT or PATCH with the same parameters in JSON or a form; `query`, `termo`, `busca` and `search` count as `q`, `estado` as `uf`, and `limit` as `limite`. Every 400 has `exemplo` and `doc`.
Annotations the server declares
- title: Awarded prices
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
claim_guest_trackingBrings into the session account what the guest edm_… created (the SDK claim): the Salvas, Alertas and Vigias that the account does not have yet, and the documents that the guest bo…No findings
Why it is in this group
- Nothing in its name or description says what it does, so it is counted as a write.
Description, as the server wrote it Brings into the session account what the guest edm_… created (the SDK claim): the Salvas, Alertas and Vigias that the account does not have yet, and the documents that the guest bought. Requires the bootstrap/CSRF of this browser; the page does it right after sign-in. It moves only what the guest still has, in one transaction; what collides with what the account already has stays with the guest. A repeat does no harm (it moves zero).
Annotations the server declares
- title: Bring guest lists into the account
- readOnlyHint: false
- destructiveHint: false
- idempotentHint: false
- openWorldHint: false
consulta_cadastroName, status, activity and address of a Brazilian company by CNPJ.No findings
Why it is in this group
- Nothing in its name or description says what it does, so it is counted as a write.
- The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.
Description, as the server wrote it Name, status, activity and address of a Brazilian company by CNPJ. It does not count against the daily free limit, does not show contacts or partners and runs no extra checks. The origin's protection limit still applies. For sanctions, tax status and a live CNIA check, use consulta_cnpj.
Annotations the server declares
- title: Company registration record
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
consulta_cepAddresses at a CEP (Brazilian postal code) with coordinates (CNEFE/IBGE) and the companies registered there.No findings
Why it is in this group
- Nothing in its name or description says what it does, so it is counted as a write.
- The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.
Description, as the server wrote it Addresses at a CEP (Brazilian postal code) with coordinates (CNEFE/IBGE) and the companies registered there. Returns up to 20 addresses and up to 20 companies; the total number of addresses is in `pontos_total`. 10 free lookups per day per network; after that, the tool answers `free_limit` with `resets_at`.
Annotations the server declares
- title: Check a CEP
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
consulta_cnpjBrazilian company record by CNPJ from the Federal Revenue (Receita Federal), with the special status when there is one (bankruptcy, judicial recovery, liquidation); its sanctions (…No findings
Why it is in this group
- Nothing in its name or description says what it does, so it is counted as a write.
- The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.
Description, as the server wrote it Brazilian company record by CNPJ from the Federal Revenue (Receita Federal), with the special status when there is one (bankruptcy, judicial recovery, liquidation); its sanctions (CEIS, CNEP, CEPIM, leniency agreements, TCU and the CNJ's CNIA, checked live); partners on the politically exposed persons list (CGU); tax status (federal tax debt, installment agreements, tax incentives and construction works); the Federal Revenue chronic tax debtor list (`devedorContumaz.consta`: barred from public tenders); environmental and labor risk (forced-labor list, Ibama embargoes and fines); government contracts (PNCP, federal contracts since 2013 and sales to municipalities in the state of SP, from TCE-SP) and BNDES financing; registrations with regulators and official registries (CVM, Central Bank, ANS, ANTT, ANP, ANEEL, Anatel, Anvisa, CNES, Cadastur, Ibama, ANAC and SICAF); CVM investment funds; and the address on the map (CNEFE/IBGE). Accepts the numeric and the alphanumeric CNPJ. Personal data in the record comes masked. `sancoes` has what public registries record against the whole company (the CNPJ root), updated daily: useful to vet suppliers. 10 free lookups per day per network; after that, the tool answers `free_limit` with `resets_at`.
Annotations the server declares
- title: Check a company (live)
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: true
consulta_enderecoAddresses and companies at a CEP (Brazilian postal code), without counting against the daily free limit.No findings
Why it is in this group
- Nothing in its name or description says what it does, so it is counted as a write.
- The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.
Description, as the server wrote it Addresses and companies at a CEP (Brazilian postal code), without counting against the daily free limit. Up to 20 addresses and 20 companies; `pontos_total` has the total number of addresses. The origin's protection limit still applies.
Annotations the server declares
- title: Addresses of a CEP
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
consulta_sugerirSuggests up to 8 Brazilian companies for a CNPJ, company name, partner, phone or e-mail, ordered by how well they match.No findings
Why it is in this group
- Nothing in its name or description says what it does, so it is counted as a write.
- The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.
Description, as the server wrote it Suggests up to 8 Brazilian companies for a CNPJ, company name, partner, phone or e-mail, ordered by how well they match. It does not count against the daily free limit and does not show contacts. `incompleto` means one of the sources did not answer.
Annotations the server declares
- title: Find a company
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
create_alertAn alert for new procurements by object terms and state (UF).No findings
Why it is in this group
- The name "create_alert" says "create": a word for a change.
Description, as the server wrote it An alert for new procurements by object terms and state (UF). Use the account session or guest token. Channels: pull, signed webhook or email. Name, organization and email recipients are optional. Two modes. By `termos`: a space requires all groups; `|` accepts alternatives within a group. By `cnpj`: known activity families produce alerts, up to `max_familias`. Unmapped activities remain in the response without an alert. The cron checks every 30 minutes. Email requires an account session and `EMAIL_ALERTAS=1`. It uses explicit recipients or the verified account email.
Annotations the server declares
- title: Create an alert
- readOnlyHint: false
- destructiveHint: false
- idempotentHint: false
- openWorldHint: true
create_alerts_by_cnpjAlerts for new procurements by the company CNPJ (requires the token edm_…): the activities (CNAE) become families of terms, and there is one alert per family, main first, up to max…No findings
Why it is in this group
- The name "create_alerts_by_cnpj" says "create": a word for a change.
Description, as the server wrote it Alerts for new procurements by the company CNPJ (requires the token edm_…): the activities (CNAE) become families of terms, and there is one alert per family, main first, up to max_familias. A CNAE outside the dictionary is listed in the response with a null family. Two modes. By `termos`: a space requires all groups; `|` accepts alternatives within a group. By `cnpj`: known activity families produce alerts, up to `max_familias`. Unmapped activities remain in the response without an alert. The cron checks every 30 minutes. Email requires an account session and `EMAIL_ALERTAS=1`. It uses explicit recipients or the verified account email.
Annotations the server declares
- title: Alerts by CNPJ
- readOnlyHint: false
- destructiveHint: false
- idempotentHint: false
- openWorldHint: true
create_ownerCreates the guest (token edm_…, issued by the account library) that opens alerts and watches, and the secret whsec_… that signs the webhooks.No findings
Why it is in this group
- The name "create_owner" says "create": a word for a change.
Description, as the server wrote it Creates the guest (token edm_…, issued by the account library) that opens alerts and watches, and the secret whsec_… that signs the webhooks. No sign-up. The token appears only once: keep it and send it in Authorization: Bearer in the alert and watch tools. The account library signs the token, with a limit per network and per hour, so the free allowance does not become infinite. The token has no recovery: sign in to the account and bring the lists into it (`POST /api/auth/claim`, which the account page does on sign-in) to stop depending on it. You can read `webhook_segredo` again in `GET /api/dono`. Each webhook POST carries `webhook-id`, `webhook-timestamp` (Unix seconds) and `webhook-signature: v1,<base64>`: HMAC-SHA256 of `id.timestamp.body` with the key of your `whsec_…` (the base64 after the prefix). This is the Standard Webhooks pattern: any of its libraries can check it; reject a timestamp outside 5 minutes. After `POST /api/dono/segredo`, the previous secret still signs for 24 h (two `v1,` parts in the header).
Annotations the server declares
- title: Create an owner
- readOnlyHint: false
- destructiveHint: false
- idempotentHint: false
- openWorldHint: false
evaluation_basicBasic native or OCR text of a PDF of up to 50 pages / 32 MiB, without review or structured tables.2 findings
Why it is in this group
- Nothing in its name or description says what it does, so it is counted as a write.
Findings
- Info
The description mentions "credential".
What this check looks forMatched text
description: "...It does not open premium. Allowance per credential, until the earlier date of the agent's..."
- Info
The input schema at properties.agent_pass.description mentions "credential".
What this check looks forMatched text
inputSchema.properties.agent_pass.description: "Persistent individual credential from POST https://api.editalmd.com/lici..."
Description, as the server wrote it Basic native or OCR text of a PDF of up to 50 pages / 32 MiB, without review or structured tables. Up to 100 documents per agent. It does not open premium. Allowance per credential, until the earlier date of the agent's 30 days and the end of the pilot. Repeating the same document does not use another unit. Premium: keep evaluation.access_code and use X-Editalmd-Avaliacao together with X-Agent-Pass in the reads and in GET /geracao. Basic does not open premium content. The pilot depends on the global budget; no automatic renewal.
Annotations the server declares
- title: Basic text of a document
- readOnlyHint: false
- destructiveHint: false
- idempotentHint: false
- openWorldHint: false
evaluation_basic_resultFollows the basic reading after retry_after_s and returns the text per page with the hash of the source.2 findings
Why it is in this group
- Nothing in its name or description says what it does, so it is counted as a write.
- The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.
Findings
- Info
The description mentions "credential".
What this check looks forMatched text
description: "...h the hash of the source. Allowance per credential, until the earlier date of the agent's..."
- Info
The input schema at properties.agent_pass.description mentions "credential".
What this check looks forMatched text
inputSchema.properties.agent_pass.description: "Persistent individual credential from POST https://api.editalmd.com/lici..."
Description, as the server wrote it Follows the basic reading after retry_after_s and returns the text per page with the hash of the source. Allowance per credential, until the earlier date of the agent's 30 days and the end of the pilot. Repeating the same document does not use another unit. Premium: keep evaluation.access_code and use X-Editalmd-Avaliacao together with X-Agent-Pass in the reads and in GET /geracao. Basic does not open premium content. The pilot depends on the global budget; no automatic renewal.
Annotations the server declares
- title: Basic reading result
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
evaluation_quotaIndividual allowance: one premium and 100 basic documents, with an expiry date.1 finding
Why it is in this group
- Nothing in its name or description says what it does, so it is counted as a write.
- The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.
Findings
- Info
The input schema at properties.agent_pass.description mentions "credential".
What this check looks forMatched text
inputSchema.properties.agent_pass.description: "Persistent individual credential from POST https://api.editalmd.com/lici..."
Description, as the server wrote it Individual allowance: one premium and 100 basic documents, with an expiry date.
Annotations the server declares
- title: Pilot allowance
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
framework_agreementsThe valid framework agreements (`ata de registro de preços`) on PNCP for the object, most relevant first: the managing agency, the validity, whether the agreement accepts joining (…No findings
Why it is in this group
- Nothing in its name or description says what it does, so it is counted as a write.
- The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.
Description, as the server wrote it The valid framework agreements (`ata de registro de preços`) on PNCP for the object, most relevant first: the managing agency, the validity, whether the agreement accepts joining (carona) and the link to the agreement. Free. Only the agreements that are not canceled and are valid today or later. `adesao=1` returns only the ones that accept joining. The procurement record (`/api/compra/:id`) has the agreements that it generated. `Accept: text/html` opens the Atas vigentes tab with the terms.
Annotations the server declares
- title: Valid framework agreements
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
get_qualificationThe qualification list of the tender, with literal excerpts: conditions, exceptions and evidence by page of the available analysis.2 findings
Why it is in this group
- The name "get_qualification" says "get": a word for reading.
- The server marks it as not read-only (readOnlyHint: false).
Findings
- Info
The input schema at properties.agent_pass.description mentions "credential".
What this check looks forMatched text
inputSchema.properties.agent_pass.description: "Individual agent credential, required together with X-Editalmd-Aval..."
- Warn
The server marks "get_qualification" as not read-only (readOnlyHint: false), and its words say it reads.
What this check looks forMatched text
annotations: {"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":false}; The name "get_qualification" says "get": a word for reading.
Description, as the server wrote it The qualification list of the tender, with literal excerpts: conditions, exceptions and evidence by page of the available analysis. The lookup does not start another analysis. Deadlines, proposals and the other obligations are in the dossier; this list covers qualification and the required attestations, and does not state what the company has.
Annotations the server declares
- title: Qualification list
- readOnlyHint: false
- destructiveHint: false
- idempotentHint: false
- openWorldHint: false
healthHealth of the origin and size of the collection (procurements and documents with text).No findings
Why it is in this group
- Nothing in its name or description says what it does, so it is counted as a write.
- The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.
Description, as the server wrote it Health of the origin and size of the collection (procurements and documents with text).
Annotations the server declares
- title: Service health
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
my_accountThe identity and the private counters of the account session (cookie) sent in the MCP request.No findings
Why it is in this group
- Nothing in its name or description says what it does, so it is counted as a write.
- The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.
Description, as the server wrote it The identity and the private counters of the account session (cookie) sent in the MCP request. The global account is already the person in EditalMD: there is no activation per product.
Annotations the server declares
- title: My account
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
my_documentsThe private collection of the account.No findings
Why it is in this group
- Nothing in its name or description says what it does, so it is counted as a write.
- The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.
Description, as the server wrote it The private collection of the account. Requires the account session (cookie and the browser CSRF).
Annotations the server declares
- title: My documents
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
my_procurementsThe private collection of the account.No findings
Why it is in this group
- Nothing in its name or description says what it does, so it is counted as a write.
- The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.
Description, as the server wrote it The private collection of the account. Requires the account session (cookie and the browser CSRF).
Annotations the server declares
- title: My procurements
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
open_tenders_in_fieldThe tenders with an open proposal period published in the last 7 days, in the state (UF) and in the CNAEs of the companies that supply the same as this procurement, highest value f…1 finding
Why it is in this group
- The name "open_tenders_in_field" says "open": a word for a change.
- The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.
Findings
- Warn
The server marks "open_tenders_in_field" read-only (readOnlyHint: true), and its own name, description or input give the class "write".
What this check looks forMatched text
annotations: {"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}; The name "open_tenders_in_field" says "open": a word for a change.
Description, as the server wrote it The tenders with an open proposal period published in the last 7 days, in the state (UF) and in the CNAEs of the companies that supply the same as this procurement, highest value first, and the alert body that delivers them (for `create_alert`). Useful when the procurement you looked up is already closed. Free. Without a CNAE, it uses the terms of the object. It is the same read as the alert preview (`POST /api/alertas/previa`), and `alerta` has the body that creates this alert in `POST /api/alertas` (add the `canal`). The result is per field and state and is kept for 30 minutes; when the service is busy or the origin is down, `estado` says so and `itens` is empty.
Annotations the server declares
- title: Open tenders in the same field
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
preview_alertA free sample of procurements by terms and filters, or editable suggestions by CNPJ.1 finding
Why it is in this group
- The name "preview_alert" says "preview": a word for reading.
- The server marks it as not read-only (readOnlyHint: false).
Findings
- Warn
The server marks "preview_alert" as not read-only (readOnlyHint: false), and its words say it reads.
What this check looks forMatched text
annotations: {"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":false}; The name "preview_alert" says "preview": a word for reading.
Description, as the server wrote it A free sample of procurements by terms and filters, or editable suggestions by CNPJ. It does not create alerts.
Annotations the server declares
- title: Alert preview
- readOnlyHint: false
- destructiveHint: false
- idempotentHint: false
- openWorldHint: false
procurement_plansWhat agencies plan to procure (annual procurement plans, PCA, on PNCP), before the tender opens: item, agency, quantity, estimated value and desired date.No findings
Why it is in this group
- Nothing in its name or description says what it does, so it is counted as a write.
- The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.
Description, as the server wrote it What agencies plan to procure (annual procurement plans, PCA, on PNCP), before the tender opens: item, agency, quantity, estimated value and desired date. Free. Only the current version of each plan; without `ano`, from the current year on. To know when the tender opens, create an alert with the same terms (`/api/alertas`). `Accept: text/html` opens the Planos de compras tab with the terms.
Annotations the server declares
- title: Procurement plans
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
request_originalWhen the person wants the document, downloads the pending original from PNCP now.No findings
Why it is in this group
- The name "request_original" says "request": a word for a change.
Description, as the server wrote it When the person wants the document, downloads the pending original from PNCP now. Free and idempotent. It does not start OCR. Use it when the person opens the document. The body is empty or {} (two bytes at most). A free collector downloads the original at once and the status becomes downloading; without a free collector, the request goes first into the queue.
Annotations the server declares
- title: Request the original
- readOnlyHint: false
- destructiveHint: false
- idempotentHint: true
- openWorldHint: true
rotate_webhook_secretChanges the secret that signs the webhooks (requires the token edm_…).No findings
Why it is in this group
- Nothing in its name or description says what it does, so it is counted as a write.
Description, as the server wrote it Changes the secret that signs the webhooks (requires the token edm_…). The previous secret still signs for 24 h, so you can change it without a failure window. During the 24 h, the `webhook-signature` header has two `v1,…` parts: one with the new secret and one with the previous. The receiver only needs to accept any part that matches.
Annotations the server declares
- title: Rotate the webhook secret
- readOnlyHint: false
- destructiveHint: false
- idempotentHint: false
- openWorldHint: false
watch_procurementWatches a procurement (requires the token edm_…): takes a snapshot now and records the events of correction, new document, suspension, postponed deadline and value, plus deadline n…No findings
Why it is in this group
- Nothing in its name or description says what it does, so it is counted as a write.
Description, as the server wrote it Watches a procurement (requires the token edm_…): takes a snapshot now and records the events of correction, new document, suspension, postponed deadline and value, plus deadline notices. The checks are periodic; check the date of the last check in the watch. The notices `prazo_impugnacao` (on the day) and `prazo_proposta` (24 h before) go out once each.
Annotations the server declares
- title: Watch a procurement
- readOnlyHint: false
- destructiveHint: false
- idempotentHint: false
- openWorldHint: true
who_suppliesThe CNAEs (activity codes) that usually win procurements like this one, most likely first, with the official description and, per CNAE, how many items and how much of the estimated…No findings
Why it is in this group
- Nothing in its name or description says what it does, so it is counted as a write.
- The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.
Description, as the server wrote it The CNAEs (activity codes) that usually win procurements like this one, most likely first, with the official description and, per CNAE, how many items and how much of the estimated value pointed to it. Free. Each item of the procurement (up to 99, the ones of highest value) points to the 3 most likely CNAEs, by a classifier trained on the activity of the companies that won similar items in the awarded PNCP results; the procurement adds the points (3, 2 and 1 by position). Without items in the collection, the object of the procurement counts, and the top 5 come without `itens` or `valor_estimado`. In the measurement of 27/09/2026, for 87% of the items one of the first 3 was a CNAE of the company that won. To receive the new procurements of these CNAEs, create an alert (`POST /api/alertas`).
Annotations the server declares
- title: Who supplies
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
Only reads 21Claude Code: allow
company_documentsLists the private PDFs of the company.No findings
Why it is in this group
- The description's first verb is "list": a word for reading.
Description, as the server wrote it Lists the private PDFs of the company. Binary downloads use the authenticated HTTP GET /documentos/:arquivo.
Annotations the server declares
- title: Company documents
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
generation_statusFollows the real phases and the completion, free, without starting processing.1 finding
Why it is in this group
- The name "generation_status" says "status": a word for reading.
Findings
- Info
The input schema at properties.agent_pass.description mentions "credential".
What this check looks forMatched text
inputSchema.properties.agent_pass.description: "Individual agent credential, required together with X-Editalmd-Aval..."
Description, as the server wrote it Follows the real phases and the completion, free, without starting processing.
Annotations the server declares
- title: Generation status
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
get_deadlinesThe deadlines of the procurement: the published end of proposals and the last day to challenge the tender (estimate: 3 business days before the session, Law 14.133 art.No findings
Why it is in this group
- The name "get_deadlines" says "get": a word for reading.
Description, as the server wrote it The deadlines of the procurement: the published end of proposals and the last day to challenge the tender (estimate: 3 business days before the session, Law 14.133 art. 164, national holidays). Free. Served from the edge cache for up to 6 hours: the record rarely changes. `Cache-Control: no-cache` in the request reads the origin now. The `x-origem-cache` header says `hit`, `miss` or `bypass`.
Annotations the server declares
- title: Procurement deadlines
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
get_documentA free lookup of the title, type, pages and the procurement linked to a document.No findings
Why it is in this group
- The name "get_document" says "get": a word for reading.
Description, as the server wrote it A free lookup of the title, type, pages and the procurement linked to a document. Use `get_procurement` to list the related documents. It does not open content or start OCR.
Annotations the server declares
- title: Document
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
get_document_dossierItems, requirements, attestations, deadlines and obligations, with conditions, exceptions and excerpts/pages.1 finding
Why it is in this group
- The name "get_document_dossier" says "get": a word for reading.
Findings
- Info
The input schema at properties.agent_pass.description mentions "credential".
What this check looks forMatched text
inputSchema.properties.agent_pass.description: "Individual agent credential, required together with X-Editalmd-Aval..."
Description, as the server wrote it Items, requirements, attestations, deadlines and obligations, with conditions, exceptions and excerpts/pages. It uses the same acesso_codigo as the reading. It does not start AI. The dossier is included in the document access, with no new analysis when you read it. Partial data tells the coverage; an export requires a finished version.
Annotations the server declares
- title: Document dossier
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
get_ownerThe owner state (requires the token edm_… or the account session): account or guest, the notice e-mail, the allowance and the secret whsec_… that signs each webhook (Standard Webho…No findings
Why it is in this group
- The name "get_owner" says "get": a word for reading.
Description, as the server wrote it The owner state (requires the token edm_… or the account session): account or guest, the notice e-mail, the allowance and the secret whsec_… that signs each webhook (Standard Webhooks: webhook-id, webhook-timestamp, webhook-signature). Each webhook POST carries `webhook-id`, `webhook-timestamp` (Unix seconds) and `webhook-signature: v1,<base64>`: HMAC-SHA256 of `id.timestamp.body` with the key of your `whsec_…` (the base64 after the prefix). This is the Standard Webhooks pattern: any of its libraries can check it; reject a timestamp outside 5 minutes. After `POST /api/dono/segredo`, the previous secret still signs for 24 h (two `v1,` parts in the header).
Annotations the server declares
- title: Owner
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
get_participationReads the state, the pending items and the met items, with reasons, actions and evidence.No findings
Why it is in this group
- The name "get_participation" says "get": a word for reading.
Description, as the server wrote it Reads the state, the pending items and the met items, with reasons, actions and evidence. It never starts an analysis. Pending items group precisa_comprovar (proof missing), divergente (incompatible evidence) and acompanhar (future obligation). A different company record, attachments or dossier return outdated without current results. The reference date stays when the analysis resumes; a previous day returns data_atual=false. Validated batches stay available during failures or processing, with parcial=true and processados/total; they never mean that the requirements not yet compared are done. GET does not run the queue and does not start AI.
Annotations the server declares
- title: Participation result
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
get_procurementThe procurement record and its documents in the collection (up to 50), with titles, types, pages and availability.No findings
Why it is in this group
- The name "get_procurement" says "get": a word for reading.
Description, as the server wrote it The procurement record and its documents in the collection (up to 50), with titles, types, pages and availability. Free. Served from the edge cache for up to 6 hours: the record rarely changes. `Cache-Control: no-cache` in the request reads the origin now. The `x-origem-cache` header says `hit`, `miss` or `bypass`.
Annotations the server declares
- title: Procurement record
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
get_reading_manifestThe document manifest: pages, images, SHA-256 and version.1 finding
Why it is in this group
- The name "get_reading_manifest" says "get": a word for reading.
Findings
- Info
The input schema at properties.agent_pass.description mentions "credential".
What this check looks forMatched text
inputSchema.properties.agent_pass.description: "Individual agent credential, required together with X-Editalmd-Aval..."
Description, as the server wrote it The document manifest: pages, images, SHA-256 and version. Send acesso_codigo; the examples are free. It does not start OCR. The same authorization opens the ZIP and the images through the API. Only ready resources. `document_approved: false` marks the automatic extraction and does not block reading.
Annotations the server declares
- title: Document reading manifest
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
get_tender_markdownReads the Markdown with the acesso_codigo of the document, or with avaliacao_codigo and agent_pass of the sponsored premium.1 finding
Why it is in this group
- The name "get_tender_markdown" says "get": a word for reading.
Findings
- Info
The input schema at properties.agent_pass.description mentions "credential".
What this check looks forMatched text
inputSchema.properties.agent_pass.description: "Individual agent credential, required together with X-Editalmd-Aval..."
Description, as the server wrote it Reads the Markdown with the acesso_codigo of the document, or with avaliacao_codigo and agent_pass of the sponsored premium. Five examples are free.
Annotations the server declares
- title: Tender Markdown
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
list_alert_matchesThe procurements that already matched an alert (pull channel), with deadlines and delivery status.No findings
Why it is in this group
- The name "list_alert_matches" says "list": a word for reading.
Description, as the server wrote it The procurements that already matched an alert (pull channel), with deadlines and delivery status. Requires the token edm_….
Annotations the server declares
- title: Alert matches
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
list_cnaesSearch term suggestions by economic activity (CNAE), with the description, the family and coverage indicators.No findings
Why it is in this group
- The name "list_cnaes" says "list": a word for reading.
Description, as the server wrote it Search term suggestions by economic activity (CNAE), with the description, the family and coverage indicators. Free. Without `q`, it lists the activities with the most registered suppliers. With `q`, it searches by code prefix (`1412`, `1412-6/01`) or by a word of the description. A null `familia` or `termos` means that the CNAE is not in the dictionary yet: an alert by CNPJ does not use it.
Annotations the server declares
- title: Activity codes (CNAE)
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
list_document_filesThe catalog of the original files of the document, with download links and pages.1 finding
Why it is in this group
- The name "list_document_files" says "list": a word for reading.
Findings
- Info
The input schema at properties.agent_pass.description mentions "credential".
What this check looks forMatched text
inputSchema.properties.agent_pass.description: "Individual agent credential, required together with X-Editalmd-Aval..."
Description, as the server wrote it The catalog of the original files of the document, with download links and pages. Use /api/documento/{id}/original to download the full original.
Annotations the server declares
- title: Document files
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
list_examplesLists five real free proofs to check the Markdown, the original PDF and the ZIP with images before you generate another document.No findings
Why it is in this group
- The name "list_examples" says "list": a word for reading.
Description, as the server wrote it Lists five real free proofs to check the Markdown, the original PDF and the ZIP with images before you generate another document.
Annotations the server declares
- title: Examples
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
list_my_companiesThe companies are the account organizations with EditalMD; use the session or the organization key.No findings
Why it is in this group
- The name "list_my_companies" says "list": a word for reading.
Description, as the server wrote it The companies are the account organizations with EditalMD; use the session or the organization key.
Annotations the server declares
- title: My companies
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
list_savedLists up to 200 tenders saved by the owner, free.No findings
Why it is in this group
- The name "list_saved" says "list": a word for reading.
Description, as the server wrote it Lists up to 200 tenders saved by the owner, free.
Annotations the server declares
- title: Saved tenders
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
list_watch_eventsThe events of a watched procurement (what changed, from what to what, and when) and the current snapshot.No findings
Why it is in this group
- The name "list_watch_events" says "list": a word for reading.
Description, as the server wrote it The events of a watched procurement (what changed, from what to what, and when) and the current snapshot. Requires the token edm_….
Annotations the server declares
- title: Watch events
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
lookup_referenceFind city names and state codes, activities and other Radar CNPJ references.No findings
Why it is in this group
- The name "lookup_reference" says "lookup": a word for reading.
Description, as the server wrote it Find city names and state codes, activities and other Radar CNPJ references. For tender filters, use the city name and state. Returned numeric codes belong to Receita, not IBGE.
Annotations the server declares
- title: Lookup reference
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
original_statusReads the status of the original, free.No findings
Why it is in this group
- The name "original_status" says "status": a word for reading.
Description, as the server wrote it Reads the status of the original, free. It does not ask for a download or a generation. It returns only the file status: it does not deliver content, grant access, confirm pages or start a generation. No query. The response is no-store.
Annotations the server declares
- title: Original file status
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
search_companiesSearches the company registry by CNPJ or company name; requires an account or a guest.No findings
Why it is in this group
- The name "search_companies" says "search": a word for reading.
Description, as the server wrote it Searches the company registry by CNPJ or company name; requires an account or a guest.
Annotations the server declares
- title: Find a company
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
search_tendersSearches public procurements by term.No findings
Why it is in this group
- The name "search_tenders" says "search": a word for reading.
Description, as the server wrote it Searches public procurements by term. Free. Returns the object, the agency, the state (UF), the modality and the procurement id.
Annotations the server declares
- title: Search tenders
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
This is not a safety rating, and no finding is not a safety guarantee. The groups and findings come from fixed checks of the tool definitions the server returned on the date shown, not from its code or what it does when called. How the checks work.
Install
Pinned to version 1.0.1. Values in angle brackets are yours to fill in.
claude mcp add --transport http editalmd https://editalmd.com/mcpRun in a terminal.
Claude Code permissions
Allow the reads, ask before a change, deny the deletes. Paste into .claude/settings.json.
{
"permissions": {
"allow": [
"mcp__editalmd__company_documents",
"mcp__editalmd__get_participation",
"mcp__editalmd__list_my_companies",
"mcp__editalmd__search_companies",
"mcp__editalmd__lookup_reference",
"mcp__editalmd__list_saved",
"mcp__editalmd__generation_status",
"mcp__editalmd__original_status",
"mcp__editalmd__list_examples",
"mcp__editalmd__get_document",
"mcp__editalmd__get_document_dossier",
"mcp__editalmd__list_document_files",
"mcp__editalmd__search_tenders",
"mcp__editalmd__get_deadlines",
"mcp__editalmd__get_procurement",
"mcp__editalmd__get_tender_markdown",
"mcp__editalmd__get_reading_manifest",
"mcp__editalmd__get_owner",
"mcp__editalmd__list_cnaes",
"mcp__editalmd__list_alert_matches",
"mcp__editalmd__list_watch_events"
],
"ask": [
"mcp__editalmd__evaluation_quota",
"mcp__editalmd__evaluation_premium",
"mcp__editalmd__evaluation_basic",
"mcp__editalmd__evaluation_basic_result",
"mcp__editalmd__attach_company_document",
"mcp__editalmd__analyze_participation",
"mcp__editalmd__awarded_prices",
"mcp__editalmd__framework_agreements",
"mcp__editalmd__procurement_plans",
"mcp__editalmd__my_account",
"mcp__editalmd__my_documents",
"mcp__editalmd__my_procurements",
"mcp__editalmd__account_tracking",
"mcp__editalmd__claim_guest_tracking",
"mcp__editalmd__preview_alert",
"mcp__editalmd__request_original",
"mcp__editalmd__api_index",
"mcp__editalmd__health",
"mcp__editalmd__who_supplies",
"mcp__editalmd__open_tenders_in_field",
"mcp__editalmd__get_qualification",
"mcp__editalmd__create_owner",
"mcp__editalmd__rotate_webhook_secret",
"mcp__editalmd__create_alert",
"mcp__editalmd__create_alerts_by_cnpj",
"mcp__editalmd__watch_procurement",
"mcp__editalmd__consulta_cadastro",
"mcp__editalmd__consulta_endereco",
"mcp__editalmd__consulta_sugerir",
"mcp__editalmd__consulta_cnpj",
"mcp__editalmd__consulta_cep"
],
"deny": [
"mcp__editalmd__remove_company_document",
"mcp__editalmd__add_company",
"mcp__editalmd__select_company",
"mcp__editalmd__remove_company",
"mcp__editalmd__update_alert",
"mcp__editalmd__save_procurement",
"mcp__editalmd__remove_saved"
]
}
}Tools that only read are allowed, tools that change things ask first, tools that delete or cancel are denied. It assumes the server is installed as editalmd. Review it before you use it.