FIN MCP Surface Architecture
Date: 2026-05-15
Status: Draft v0.1
Related: docs/engineering/FIN_INTRANET_HUMAN_AGENT_PROJECTION_ENGINEERING_SPEC_2026-05-13.md,
docs/engineering/FIN_AGENTIC_HARNESS_SPEC_2026-05-15.md,
docs/product/FIN_PRODUCT_TIER_ARCHITECTURE_2026-05-15.md
0. Purpose
Every external capability of FIN is exposed as one or more MCP tools. The MCP catalog is FIN’s contract surface for agents — internal agents, tenant agents, partner agents, federal agents, and public Tier 0 agents.
This doc defines the three MCP surfaces (internal / tenant / public), authentication, versioning, deprecation, rate limiting, metering, and the registry that catalogs every tool.
If MCP tools or contracts diverge across docs, this doc is the source of truth.
1. Three MCP Surfaces
The three surfaces never share infrastructure or trust. Audience class determines route, route determines tool catalog, tool catalog determines capability.
1.1 Internal MCP
- Audience: privileged service accounts (FIN ops, OpenClaw mediator, CI runners)
- Trust: inside the platform trust boundary, full data plane access for FIN operators
- Auth: service-account JWT signed by platform key, short-lived (1 hour)
- Tool catalog: ~350 tools today, the existing
index.tscatalog - Routes: internal-only, network-isolated, never exposed publicly
1.2 Tenant MCP
- Audience: tenant-owned agents acting on behalf of the tenant
- Trust: tenant trust boundary, full access to tenant’s data plane
- Auth: tenant JWT issued by tenant’s OAuth flow, refresh-token based,
actor-scoped (every JWT carries
actor_idandactor_role) - Tool catalog: subset of internal MCP — excludes platform-admin tools, federal-audience tools (unless tenant has federal add-on), and cross-tenant tools
- Routes: per-tenant subdomain or path (e.g.
https://nathel.fin.app/api/v1/mcp/)
1.3 Public Tier 0 MCP
- Audience: external developers, university researchers, federal read-only consumers, partner agents, consumer apps
- Trust: zero trust, public boundary
- Auth: API key issued per developer/org, key carries quota and rate limit
- Tool catalog: strictly read-only over Plane 3 (universal intelligence + Harvest Directory). No tenant-private data. No write tools. No proposal tools.
- Routes:
https://api.harvestdirectory.org/v1/mcp/(separate domain, separate certs, separate WAF policy)
Surfaces NEVER share an MCP server instance even if they happen to expose
identically-named tools. A search_docs on Internal returns full
tenant docs; a search_docs on Tier 0 returns Harvest Directory only.
Different routes, different filters, different audit retention.
2. Tool Registry
2.1 Registry Storage
The MCP tool registry lives as knowledge.domain = mcp_tool rows. One
row per (tool_name, version, surface). Carries:
type McpToolRegistryEntry = {
tool_name: string;
version: string; // semver
surface: "internal" | "tenant" | "public_tier_0";
audience_class: string[]; // which audiences may call
input_schema: JsonSchema;
output_schema: JsonSchema;
capability_description: string;
rate_limit: { per: "session" | "minute" | "hour" | "day"; max: number };
cost_cents_per_call?: number;
privileged: boolean;
goes_through_openclaw: boolean;
ships_in_tier: Array<"T0" | "T1" | "T2" | "T3" | "T4">;
deprecated: boolean;
deprecation_date?: string;
successor_tool?: string;
lifecycle_status: "alpha" | "beta" | "ga" | "deprecated" | "retired";
};2.2 Registry Projection
mcp_tool_registry_projection (Wave 2 CQRS projection, migration 047) is
the read model. Updated on mcp.tool_registered, mcp.tool_version_bumped,
mcp.tool_deprecated events.
2.3 Registry Discovery
list_tools(surface) returns the registry filtered by surface and the
caller’s authorization. Tier 0 callers see only the Tier 0 catalog. Tenant
callers see only what their role + tier permits.
Public documentation site (api.harvestdirectory.org/docs/) is the
human-readable rendering of the public-Tier-0 portion of the registry,
auto-generated.
3. Versioning
3.1 Semantic Versioning
Tool versions follow semver:
- Major bump: breaking change (input schema removes required field, output schema removes promised field, semantics change)
- Minor bump: additive change (new optional input, new output field)
- Patch bump: implementation change with identical contract
3.2 Version Negotiation
MCP callers pin a version: mcp/v2/get_doc calls v2 explicitly. Latest
within a major version is the default if pinned only to major (mcp/v2/).
Unpinned calls go to the registry’s default_version field (initially
ga-pinned, eventually rolls forward on minor bumps).
3.3 Breaking Change Policy
- Public Tier 0: announce window of 6 months before major version retired. Dual-route required for the announce window. Successor tool documented.
- Tenant MCP: announce window of 3 months. Dual-route required. Active tenant migration outreach.
- Internal MCP: announce window of 2 weeks. Dual-route optional.
3.4 Deprecation Events
mcp.tool_deprecated emitted with deprecation date and successor. The
registry shows deprecation status. Tool documentation shows the warning.
Callers receive deprecation header Sunset: and Successor: on every
call.
4. Authentication
4.1 Internal Surface
- Mutual TLS between platform services
- Service-account JWT for non-service callers (CI, operators)
- JWT signed by HSM-backed platform key
- 1-hour expiry, no refresh
- Audit of every call
4.2 Tenant Surface
- Tenant OAuth 2.1 flow (PKCE, refresh tokens)
- Actor scope: every JWT carries
tenant_id,actor_id,actor_role,tier,granted_scopes[],expires_at - Refresh tokens 30-day, access tokens 1-hour
- Granular scope: per-projection, per-MCP-tool, per-portal
- M2M variant for tenant-owned agents acting as a service account
4.3 Public Tier 0 Surface
- API key issued per developer
- Key carries: tier (free / developer / team / enterprise), quota, rate limit, attribution requirements, contact email
- Keys are bearer tokens; rotation supported
- For higher tiers, optional OAuth client credentials with per-app scoping
- Public docs require key, free tier accepts anonymous with stricter quota
4.4 Federal Audience Auth
Federal callers (when federal mode is on) use:
- FedRAMP-compliant identity provider integration
- PIV/CAC card support for direct human callers
- Service account with per-agency attestation
- Audit export to agency-specified format
5. Rate Limiting & Quota
5.1 Rate Limiter
RateLimiterDO Durable Object enforces per-key, per-tenant,
per-actor limits with sliding-window counters. Limits configured per
tier (Tier 0 free: 1K/month; Tier 0 dev: 100K/month; etc.).
5.2 Quota Enforcement
Quotas reset per the registry’s rate_limit.per field. Soft limit
emits warnings; hard limit returns 429 QuotaExceeded with reset time.
5.3 Burst Handling
Token-bucket allows brief bursts up to 2x sustained rate, then enforces sustained limit. Configurable per tier.
6. Metering
6.1 Usage Events
Per Projection Spec §5: every MCP call emits mcp.call_logged and
mcp.usage_metered.
mcp.call_logged: tool, version, surface, audience, tenant_id, actor_id,
request_id, success, latency, error_class. High volume; goes to events
with shorter retention (90 day) than other event families.
mcp.usage_metered: aggregated periodic events for billing. Computed by
a metering projection that aggregates mcp.call_logged by tenant +
window. Used to drive invoicing.
6.2 Billing Integration
Metering projection feeds Stripe (or other billing) via webhook on period close. Disputed calls have full event-stream replay capability.
6.3 Cost Telemetry
Per-call cost (LLM cost + infra cost) is computed when the tool is also an LLM call. Cost telemetry feeds the harness’s cost budget enforcement (Harness Spec §10.3).
7. Capability Advertisement
7.1 list_tools
Every surface exposes list_tools() returning the audience-appropriate
catalog. The response shape matches the MCP protocol’s standard
capability advertisement.
7.2 Tool Discovery Manifests
For each surface, a static manifest at:
- Internal:
internal.fin.app/mcp/manifest.json - Tenant:
<tenant>.fin.app/mcp/manifest.json - Public:
api.harvestdirectory.org/mcp/manifest.json
Manifests are versioned and signed. Clients verify signature before trusting the tool list.
8. Public Documentation Site
8.1 Site Structure
api.harvestdirectory.org/docs/:
- Home (intro, quick start, “hello world”)
- Tools (reference per tool, generated from registry)
- Concepts (entity profiles, citations, anonymization, planes)
- Cookbook (worked examples)
- Changelog
- Status (uptime, deprecations)
- SDK downloads (per-language wrappers)
8.2 Generated Reference
Tool reference is generated from the registry — input/output schemas, examples, error codes, rate limits. Single source of truth means docs never drift from contract.
8.3 Try-It Console
Every tool reference page includes a “try it” console that uses the caller’s API key to make live calls against a sandbox tenant or against the actual Tier 0 surface (rate-limited).
9. The Five Core Tier 0 Tools
The minimum viable Tier 0 surface is five tools. Everything else is additive.
9.1 search_docs
Read-only search over Harvest Directory.
input: { query, filters?, top_k?, retrieval_modes? }
output: { results: Array<DocSummary & { citations[] }>, total }
9.2 get_doc
Fetch a public doc by ID.
input: { doc_id }
output: DocContent (visibility: public_anonymized only)
9.3 get_entity_profile
Convenience: fetch entity profile (commodity/variety/region/etc.) with structured + markdown.
input: { entity_type, entity_id_or_slug, snapshot_period? }
output: { structured, markdown, citations[] }
9.4 list_recent_changes
The public change feed of Harvest Directory updates.
input: { since, doc_kinds?, entity_types? }
output: { changes: Array<{ doc_id, change_type, occurred_at }>, next_cursor }
9.5 walk_provenance
Walk citations from a public claim to source events / external sources.
input: { doc_id, anchor?, depth? }
output: { walk: Tree<ProvenanceNode> }
Note: walk_provenance for public Tier 0 returns the public chain. Tenant events behind anonymization are summarized as “derived from N observed events” without exposing event IDs.
10. Tenant-Surface Adds
In addition to the Tier 0 five, Tenant MCP exposes the full operator and ops agent toolkit. The most important additions:
get_tenant_doc(full visibility within tenant)get_event(raw event access)query_knowledge(structured queries on tenant knowledge rows)query_operational_memory(semantic search on tenant chunks)propose_doc_edit(agent enrichment loop)assemble_recall_trace(privileged role only)get_actor_memory(read actor memory in scope)update_actor_memory(write actor memory)record_event(with capability restriction)list_affordances(current session affordances)
Full tenant catalog ships per Tier 2 entitlement.
11. Internal-Surface Adds
Internal-only tools:
platform_admin.*(tenant lifecycle, config, capability grants)replay_session(session_id, mode)(harness replay)force_projection_rebuild(projection_name)(CQRS reset)emit_signal(*)(synthetic events for testing)walk_provenance_admin(full chain including private metadata)openclaw.*(mediator-only)
Never exposed via tenant or public surfaces, even for FIN-operator sessions on a tenant’s behalf.
12. Federal Audience
Federal mode adds:
assemble_recall_tracewithaudience: "regulator"export_audit(window, format)produce_fsma_204_filing(lot_ids)verify_sbom(version)
These are versioned, FedRAMP-routed, audited at federal-grade retention.
13. SDK Distribution
Wave 4 deliverable: official SDKs.
- TypeScript / JavaScript (primary; mirrors MCP protocol)
- Python (research, USDA, university audience)
- Go (large enterprise + government)
- Rust (performance-sensitive integration)
Each SDK is generated from the registry — tool signatures, input/output types, error classes — so SDKs never drift from contract.
14. Anti-Abuse
14.1 Patterns To Block
- Tenant identity enumeration via Tier 0 (e.g., probing
commodity_situationprojections to identify which tenant published) - Scraping at near-rate-limit for de-anonymization purposes
- Use of Tier 0 in violation of attribution requirements (free tier requires public credit per anonymization policy)
14.2 Detection
- Cross-IP key sharing
- Anomalous query patterns vs. tier-typical baselines
- Failed attempts at tenant-private endpoints
- Honeypot tools that should never be called legitimately
14.3 Enforcement
- Soft: warnings, attribution audits
- Medium: rate-limit downgrade, key reset required
- Hard: key suspension, IP block, ban list
15. Tests
15.1 Unit Tests
- registry CRUD
- version-negotiation logic
- rate-limiter token bucket
- API key validation + scope check
- tool dispatch routing per surface
15.2 Integration Tests
- end-to-end Tier 0 free-tier signup → first call
- tenant OAuth flow → tenant agent calls tenant tool
- deprecated tool returns Sunset header
- federal-mode call to federal-only tool succeeds; non-federal fails
- cross-surface isolation: public key cannot call tenant route even by full URL
- metering event volume balances against expected per-tier usage
15.3 Adversarial Tests
- enumeration attempt via Tier 0 (must be detected)
- mismatched-surface call (must be rejected at route)
- malformed JWT (must be rejected at auth)
- expired API key (must be rejected with clear error)
- privileged-tool call from non-privileged actor (must be rejected at capability check)
16. Proof Gates
Wave 1 MCP is not complete until:
- registry schema lands and one production projection (047) populates
- internal + tenant surfaces have explicit route separation
- versioned tool naming convention enforced (
mcp/v1/<tool>) list_toolsreturns audience-filtered catalog- rate limiter active for tenant surface
Wave 2 MCP is not complete until:
- five Tier 0 tools implemented (against internal test fixtures, not public)
- tenant OAuth flow ships
- metering events flow to billing-ready projection
Wave 3 MCP is not complete until:
- Public Tier 0 surface deploys to
api.harvestdirectory.org - API key issuance flow self-service
- Public docs site auto-generated from registry
- Deprecation policy enforced (one tool intentionally deprecated as a test)
- Anti-abuse detection active
Wave 4 MCP is not complete until:
- TypeScript SDK + Python SDK published
- Federal mode FedRAMP-routed and audited
- A2A primitives ship (cross-tenant blinded calls)
17. Stop Conditions
- registry cannot be made the single source of truth (docs drift) → return to architecture
- versioning policy cannot be enforced at the router layer → return to architecture
- Tier 0 isolation leaks tenant data via any tool → emergency review
- federal-mode audit cannot be made federal-grade → defer federal product
- rate limiter cannot handle target QPS → infra review
18. Out Of Scope For v0.1
- GraphQL surface (REST + MCP is sufficient; GraphQL adds complexity without commensurate value)
- gRPC surface (MCP is the agent contract; gRPC for service-to-service is internal infra not exposed)
- federated MCP (cross-platform discovery) — deferred
- bring-your-own-LLM in Tier 0 — deferred