MCP tool schema reference (V2)
ERPBridge uses a Kubernetes-style declarative resource format to define tools. This format versions tools, makes their intent clear, and separates them from the ERP structure.
Resource structureโ
A tool definition is composed of four main sections: apiVersion/kind, metadata, spec, and status (internal only).
apiVersion: erpbridge.io/v1
kind: MCPTool
metadata:
name: list_employees
version: 1.2.0
module: hr
spec:
description: { ... }
annotations: { ... }
inputSchema: { ... }
execution: { ... }
security: { ... }
cache: { ... }
routing: { ... }
Field definitionsโ
metadataโ
Identity and grouping information. On first apply, ERPBridge records a canonical executable-content SHA-256 digest and server-authored admission bookkeeping. The digest includes the tool contract, schemas, policy, and ERP mapping. It excludes runtime lifecycle fields and review bookkeeping. Identical reapply requests are idempotent. Changed content under an admitted name and version returns REGISTRY_CONFLICT; create and review a new version.
The first active version becomes the unqualified serving revision. Set isServing: true while applying an admitted active version to move that pointer. Other active versions remain available through their exact MCP names or resource digests.
name: (String) Unique identifier. Use intent-based names such aslist_employees, not technical names such asget_resource_employee.version: (String) SemVer version (e.g.,1.0.0).module: (String) Logical grouping for access control and organization.isActive: (Boolean, optional) Soft-delete flag. Whenfalse, the exact revision cannot execute but stays in the registry.isServing: (Boolean, optional) Selects this active version for future unqualified calls. It does not change in-flight calls.
spec.descriptionโ
High-signal information to help the LLM select the correct tool.
short: (String) Concise summary of what the tool does.whenToUse: (Array) List of scenarios where this tool is appropriate.whenNotToUse: (Array) List of similar scenarios where you must not use this tool.examples: (Array) Sample user queries that trigger this tool.
spec.annotationsโ
Optional MCP behavioral hints. These fields are additive and do not change the input or output schema.
title: (String, optional) Human-readable display title.readOnlyHint: (Boolean, optional) Whether the tool is expected not to modify its environment.destructiveHint: (Boolean, optional) Whether a modifying operation may be destructive.idempotentHint: (Boolean, optional) Whether repeated calls with the same arguments are expected to have no additional effect.openWorldHint: (Boolean, optional) Whether the tool interacts with external entities.
Generated annotations are method-based draft hints. Review them before applying a generated manifest. They do not replace authorization or other server-side controls.
spec.rateLimit and spec.concurrencyโ
Optional execution protection for high-volume or expensive tools.
rateLimit.requestsPerSecond: Positive finite per-tool token-bucket rate.rateLimit.burst: Positive per-tool token-bucket burst size.concurrency.limit: Positive maximum number of active calls.concurrency.perPrincipal: Whentrue, apply the active-call limit per authenticated principal or MCP session; whenfalse, share it across the tool. The global principal/session limiter remains in effect for every tool.
Unconfigured tools retain the server defaults. Side-effecting ERP methods are not automatically retried.
MCP discovery metadataโ
During MCP tools/list, ERPBridge projects existing guidance into namespaced
_meta keys:
io.erpbridge/whenToUseio.erpbridge/whenNotToUseio.erpbridge/examplesio.erpbridge/allowedRolestoolplane.resourceDigesttoolplane.resourceVersiontoolplane.serving
Every active revision also appears under a protocol-safe exact name ending in .rev_<encoded-version>. The .rev_ marker is reserved and cannot occur in a declarative tool name. An MCP client can instead send the discovered digest as params._meta.toolplane.resourceDigest. Exact and digest-bound calls validate and execute that active revision and never fall forward to another revision. ERPBridge clones the selected resource before schema validation and middleware construction, so serving-pointer changes do not alter an in-flight call. Cache entries are scoped by resource digest, or by version for programmatic tools without a digest.
These values are informational. allowedRoles describes the server's tool
allow-list; it does not grant access or replace server-side authorization. MCP
clients may show or ignore custom _meta, and they may not forward it to the
model context.
spec.inputSchemaโ
Standard JSON Schema defining the arguments. Strict typing is required.
- Use
propertiesto define fields andrequiredto enforce them. - Nested objects use nested
propertiesandrequired; arrays useitems. - Avoid "filters" strings: Break down complex query requirements into individual typed properties.
spec.outputSchemaโ
Optional JSON Schema describing the shape of a successful ERP response. When present, the server validates every 2xx response against it at runtime using jsonschema/v6.
- A response that violates the schema fails the tool call with a validation error instead of returning malformed data to the agent.
- Generated schemas come from the OpenAPI
200/201response definitions and are dereferenced (no$ref). - The schema must have a non-empty top-level string
type, such asobjectorarray. bridgectl tool validaterejects an untyped schema. MCP discovery omits an untyped legacy schema. Runtime accepts any JSON result for that legacy schema.- OpenAPI generation omits
outputSchemawhen the response has no top-level type.
spec.executionโ
Technical mapping to the ERP API.
type: (String) Execution style. Currently onlyhttp.method: (String)GET,HEAD,POST,PUT,PATCH,DELETE,OPTIONS, orTRACE.endpoint: (String) The ERP API URL path.approvedOrigins: (Array) Exact normalizedscheme://host[:port]values allowed after runtime endpoint rewriting. When omitted, apply binds the effective origin derived fromendpointand the currentERP_BASE_URL. A later rewrite to another origin fails before connector entry.mapping: (Map) Optional. Maps LLM arg names to ERP parameter names.parameterLocations: (Map) Generated metadata mapping each LLM argument topath,query,header, orbody. If absent, GET arguments use the query and other methods use one JSON object body for compatibility.bodyArgument: (String) Generated complete-body argument for primitive or array JSON request bodies. Its value is serialized as the complete body instead of an object property.responsePath: (String) Optional JSON key to extract from the ERP response. OpenAPI generation emitsdataonly when the resolved top-level response schema is an object with a top-leveldataproperty; the output schema then describes that unwrapped value.
Generated path values are URL-escaped. Generated headers are allowlisted and
cannot replace connector authentication or transport headers. Authorization,
Proxy-Authorization, Cookie, Host, connection, transfer, upgrade,
Content-Length, and Content-Type parameters are rejected during generation.
A successful HEAD or 204 No Content response returns a successful nil
result without JSON decoding.
spec.securityโ
Authentication strategy.
authType:api-key,bearer, orbasic.authHeader: (Optional) The outbound HTTP header that carries the resolved credential, such asX-API-Key. When omitted, the connector usesAuthorizationfor backward compatibility. This is a header name only; never put a credential value here.credentialRef: A logical reference, normally the name of the environment variable containing the secret. Never embed raw secrets here.credentialSource: (Optional)envorfile; omitted meansenv.filereads<ERPBRIDGE_CREDENTIALS_DIR>/<credentialRef>immediately before each request and never falls back to the environment.dataClass: (Optional string) Declared sensitivity:public,internal,pii, orrestricted. Older manifests may omit this field.allowedRoles: (Optional array) Roles that may call this tool. Values must match[a-z][a-z0-9_-]{0,63}, be unique, and contain no more than 32 roles.piiandrestrictedtools must provide at least one role.
When allowedRoles is present, the tool is guarded. MCP clients select a role
with arguments.role; direct callers use X-ERPBridge-Role. The selector
must be present in both the caller identity and the tool allow-list, and the
MCP selector is removed before execution. A guarded tool cannot define or
require its own role argument. Without allowedRoles, role remains an
ordinary business argument. Use opaque, non-identifying role slugs; never use a
person name, email, employee number, or ERP record. ERPBridge does not infer PII
from arbitrary ERP response data. Authorization runs before cache lookup and
ERP work.
The admission controller rejects tool definitions whose endpoint path contains secret-like patterns (e.g., token or key=). Credentials are resolved from environment variables at call time only.
spec.routingโ
Optional hints that improve LLM tool selection.
priority: (Number) Relative preference when several tools could answer. Higher wins.signals: (Array of strings) Positive trigger phrases for this tool.antiSignals: (Array of strings) Phrases that must not trigger this tool.
spec.lifecycleโ
Optional support status for a tool version.
status:stable,deprecated, orsunset.deprecatedAt: (String, optional) ISO date when deprecation started.sunsetAt: (String, optional) ISO date when the tool is removed.replacement: (String, optional) Name of the tool that replaces this one.
Generated drafts and reviewed manifestsโ
Generation is pure: bridgectl tool generate writes only to its selected
output stream. Keep reviewed manifests under manifests/<module>/; do not
create competing generated JSON files or use schemas/ as an authoritative
source. Generated GET and HEAD tools default to a shared read-only cache with a
five-minute TTL. Generated write methods default to no cache. Generated tools
also include method-based annotation hints for recognized HTTP methods. Unknown
methods retain only the HTTP-backed open-world hint. Review intent, roles, data
class, annotations, schemas, and cache policy before applying.
The development-only system.*_test tools require
MCP_ENABLE_TEST_TOOLS=true and must be absent from production discovery.
RedisInsight is for local inspection and must remain loopback-only or opt-in.
Annotated exampleโ
apiVersion: erpbridge.io/v1
kind: MCPTool
metadata:
name: create_purchase_invoice
version: 1.0.0
module: finance
spec:
description:
short: "Create a new purchase invoice draft."
whenToUse:
- "User wants to record a new supplier bill"
- "Adding an invoice to the finance module"
inputSchema:
type: object
properties:
supplier:
type: string
description: "The name of the vendor"
amount:
type: number
description: "Total invoice amount"
required: ["supplier", "amount"]
execution:
type: http
method: POST
endpoint: "/api/resource/Purchase Invoice"
responsePath: "data" # ERP returns { "data": { ... } }, we only want the inner object
security:
authType: api-key
authHeader: X-API-Key # Optional; defaults to Authorization
credentialRef: ERP_FINANCE_KEY # Logical reference; resolves from the environment by default
# credentialSource: file # Reads ERPBRIDGE_CREDENTIALS_DIR/ERP_FINANCE_KEY
allowedRoles: [finance_reader, finance_writer]
cache:
enabled: false # Don't cache write operations
flushOn: ["list_purchase_invoices"] # Flush list cache when a new one is created
flushOn is the schema fieldThe cache invalidation field is flushOn โ an array of tool names to flush when this tool runs. The older invalidateOn spelling is not read by the server and is ignored silently; use flushOn.
Transitioning from V1โ
If you have old schemas, use bridgectl tool generate to convert them, or manually update the following:
- Wrap the schema in
spec. - Move
name,version,moduletometadata. - Separate
endpointintoexecutionandsecurity. - Use lowercase names with underscores.