Skip to content

Fix registration & discovery papercuts#4

Merged
gabrielbauman merged 2 commits into
mainfrom
gbauman/papercuts
Jun 3, 2026
Merged

Fix registration & discovery papercuts#4
gabrielbauman merged 2 commits into
mainfrom
gbauman/papercuts

Conversation

@gabrielbauman

Copy link
Copy Markdown
Owner

Summary

Fixes the registration & discovery papercuts hit while driving the server
through several real registrations. The execute-TypeScript-in-a-sandbox core is
untouched; these are all rough edges in registration and discovery.

Changes

Re-registering an existing id no longer dead-ends

  • add_api / add take force (CLI: --force) to upsert an existing
    id in place instead of erroring. The overwrite uses a fresh addedAt (so
    serve's ops cache invalidates) and preserves same-id keystore secrets, so
    an OAuth API stays logged in across a base-URL correction. Secrets the new auth
    no longer references are cleaned up.
  • New remove_api MCP tool, sharing a single unregisterApi with the
    remove CLI (entry + secrets + cached artifacts). The agent can now sweep up
    its own mistaken registrations.

Base-URL derivation reads path/operation-level servers

  • resolveBaseUrl now scans document → path-item → operation level servers
    before falling back to the spec host, and fails loudly when the derived
    base lands on a known raw-spec-hosting host (raw.githubusercontent.com, gist,
    githack, jsDelivr, statically) instead of registering a base that would send
    every request to a file CDN. This is exactly the Open-Meteo case (no top-level
    servers, an absolute server under /v1/forecast).

execute opt-outs

  • check: false drops --check for one run, so a stale spec enum doesn't
    block a value the live API still accepts. It removes only --check — the
    --allow-net/--allow-env sandbox grants are unconditional.
  • timeoutMs raises the 30s default (capped at 120s) for long/paginated runs.

Discovery

  • search surfaces each param's description and allowed enum values
    (OpenAPI + GraphQL), size-capped, so the model needn't guess valid arguments.
  • execute's description documents the GraphQL (client.query/client.mutate)
    and SOAP (client.Operation) client shapes, not just openapi-fetch.
  • New list_apis tool returns the registry as JSON.

Not included

Pagination-aware helpers — a real cross-protocol design question rather than a
mechanical fix; the configurable timeoutMs covers the "long loops hit the 30s
wall" part. Can be designed separately.

Verification

deno task check && deno task lint && deno task fmt pass. Exercised end-to-end
against the live Open-Meteo and Petstore specs in an isolated config/cache dir:
base URL derives to https://api.open-meteo.com; a real call with
daily: ["snowfall_sum"] (absent from the spec enum) returns HTTP 200 under
check:false; --force, remove_api, list_apis, and the raw-host failure all
behave as intended. No test suite exists yet, so verification was manual.

Smooths the rough edges hit while driving the server through real
registrations; the core search/execute model is unchanged.

- add_api/add gain force (CLI: --force): upsert an existing id in place
  instead of failing. Overwrite is in-place (fresh addedAt invalidates
  serve's ops cache) and preserves same-id keystore secrets, so an OAuth
  API stays logged in across a base-URL correction.
- New remove_api MCP tool plus a shared unregisterApi, so the agent can
  clean up a mistaken registration itself (entry + secrets + cached files).
- OpenAPI base-URL derivation now reads document-, path-, and
  operation-level servers, and fails loudly when the result lands on a raw
  spec-hosting host (raw.githubusercontent.com, jsDelivr, githack, ...)
  rather than registering a base that points every call at a file CDN.
- execute gains per-call check:false (bypass a stale spec enum that rejects
  a value the live API accepts) and timeoutMs (default 30s, capped 120s).
  check:false drops only --check; the net/env sandbox grants are unchanged.
- search surfaces each param's description and allowed enum values
  (OpenAPI + GraphQL), so the model needn't guess valid arguments.
- execute's description documents the GraphQL (client.query/mutate) and
  SOAP (client.Operation) client shapes, not just openapi-fetch.
- New list_apis tool returns the registry as JSON.
Copilot AI review requested due to automatic review settings June 3, 2026 02:19

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR smooths the API registration and discovery workflow for anyapi-mcp by adding upsert/removal capabilities, improving OpenAPI base-URL derivation, and enriching the metadata surfaced by search/execute for better agent-driven usage.

Changes:

  • Add “force upsert” registration and introduce a unified unregisterApi used by both CLI (remove) and MCP (remove_api), plus a new list_apis tool.
  • Improve OpenAPI base URL derivation by scanning document/path/operation servers and rejecting known raw-spec hosting hosts.
  • Enhance discovery/execution ergonomics: parameter description/enum surfaced in search, and execute adds check:false and timeoutMs.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/register.ts Adds force upsert support, orphaned-secret cleanup, and unregisterApi for CLI/MCP removal.
src/operation.ts Extends operation param metadata with description and enum, including size clamping helpers.
src/openapi.ts Extracts/clamps param descriptions/enums and improves base URL resolution across server levels with raw-host detection.
src/graphql.ts Adds param descriptions and GraphQL enum-value surfacing into the operation index.
src/execute/run.ts Adds per-run sandbox options (check, timeoutMs) and clamps timeout values.
src/commands/serve.ts Expands MCP server tools (list_apis, remove_api), extends execute args, and updates tool descriptions.
src/commands/remove.ts Refactors CLI removal to call shared unregisterApi.
src/commands/add.ts Adds --force and reports “Re-registered” when overwriting.
README.md Documents new tools/flags and updated execute options/behavior.
CLAUDE.md Updates architecture/invariants documentation to reflect new features and options.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/operation.ts Outdated
Comment on lines +40 to +47
/** Cap an enum list, appending a count sentinel (not a real value) when truncated. */
export function clampEnum(values: string[]): string[] | undefined {
if (values.length === 0) return undefined;
if (values.length <= MAX_ENUM_VALUES) return values;
return [
...values.slice(0, MAX_ENUM_VALUES),
`… (${values.length - MAX_ENUM_VALUES} more; see generated types)`,
];
Comment thread src/register.ts
Comment on lines +262 to +264
if (existing.typesPath !== entry.typesPath) {
await Deno.remove(existing.typesPath).catch(() => {});
}
- applyEnum caps the surfaced enum to real values only; an over-cap count
  is noted in the param description instead of a sentinel enum entry a
  caller might select and send to the API.
- Overwrite's stale-types cleanup ignores only NotFound and rethrows other
  errors, matching the repo's other deletion sites.
@gabrielbauman gabrielbauman merged commit 844e71f into main Jun 3, 2026
4 checks passed
@gabrielbauman gabrielbauman deleted the gbauman/papercuts branch June 3, 2026 02:28
@gabrielbauman gabrielbauman restored the gbauman/papercuts branch June 3, 2026 02:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants