Expose a Proto Method as an Agent Tool
You need to make a new gRPC method available to agents as an MCP
tool. The method already exists in a proto file and the service
implements it, but agents cannot see it yet. Rather than writing a
tool schema by hand or adding registration code, you add a single
entry to config/config.json and rerun codegen.
@forwardimpact/libmcp reads that config at startup and
registers the tool with its parameter schema derived directly from
the proto definition.
For the full workflow of setting up typed service contracts from scratch, see Keep Service Contracts Typed.
Prerequisites
- Node.js 18+
- A working Guide installation with services running (see Getting Started)
-
@forwardimpact/libmcpand@forwardimpact/libtypeinstalled:
npm install @forwardimpact/libmcp @forwardimpact/libtype
-
The proto method you want to expose is already defined in a
.protofile and implemented in the corresponding service
Overview
Registering a tool takes two steps:
| Step | What you do | What happens |
|---|---|---|
| 1 | Add a tool entry to config.json |
Maps a tool name to a package.service.method path
|
| 2 | Run codegen | Generates metadata so libmcp can build the Zod schema |
No code changes are needed. The MCP server reads
config.json on startup, looks up each method's
field metadata from @forwardimpact/libtype, builds a
Zod schema from the proto field definitions, and registers the tool
on the MCP server.
Step 1: Add the config entry
Open config/config.json and add a new key under
service.mcp.tools. The key is the tool name agents will
see. The value needs two fields:
-
method-- the fully qualified proto method path aspackage.Service.Method -
description-- a one-line description agents read to decide when to use the tool
For example, to expose the DescribeProgression method
from the Pathway service:
{
"service": {
"mcp": {
"tools": {
"DescribeProgression": {
"method": "pathway.Pathway.DescribeProgression",
"description": "Compute the progression delta between two levels of the same discipline."
}
}
}
}
}
The method path has three parts:
| Part | Source | Example |
|---|---|---|
package |
The package declaration in the proto file |
pathway |
Service |
The service block name in the proto file |
Pathway |
Method |
The rpc method name |
DescribeProgression |
These must match the proto definition exactly. If the proto file
declares package pathway; and
service Pathway { rpc DescribeProgression(...) ... },
then the method path is
pathway.Pathway.DescribeProgression.
Step 2: Run codegen
Codegen reads the proto files and produces the metadata that
libmcp needs at runtime. Without this step, the new
method has no field metadata and registration will fail with a
"no metadata" error.
npx fit-codegen --all
This generates metadata.js inside
@forwardimpact/libtype, which contains the request type
name and field definitions for every proto method. The
registerToolsFromConfig function consults this metadata
to build the tool's parameter schema automatically.
Verify the tool is registered
Restart the MCP server, then check that the tool appears. The server logs each registered tool at startup. You can also verify by connecting an MCP client and listing available tools:
npx fit-guide tools
Expected output includes your new tool name alongside the existing tools:
GetOntology Returns all entity types and relationship predicates in the knowledge graph.
GetSubjects Lists entity URIs in the graph, optionally filtered by type.
QueryByPattern Retrieves structured data by traversing graph relationships using triple patterns.
SearchContent Find detailed content using semantic similarity search.
ListJobs List jobs (discipline x level x track) defined in the pathway standard.
DescribeJob Describe a job at (discipline, level, optional track) including skills, behaviours, and responsibilities.
DescribeProgression Compute the progression delta between two levels of the same discipline.
...
If the tool does not appear, check:
-
The
methodpath inconfig.jsonmatches the proto definition exactly (package, service, and method names are case-sensitive) - Codegen has been run after the proto file was last changed
-
The gRPC client for the method's package is passed to
registerToolsFromConfig(the MCP server must create a client for each package it uses)
How parameters are derived
You do not write parameter schemas. libmcp reads the
proto message fields from codegen metadata and builds a Zod schema
for each tool:
-
Scalar fields (
string,int32,bool, etc.) become their Zod equivalents -- all marked optional so agents can omit fields they do not need -
Repeated fields accept either a single value or
an array --
libmcpnormalizes single values into arrays before calling the gRPC method -
System fields (
llm_token,filter,resource_id) are excluded automatically -- agents never see them - Nested message fields are excluded -- only flat scalar parameters are exposed
Field descriptions come from proto comments. If a proto field has a comment above it, that comment becomes the parameter description agents see when inspecting the tool schema:
message DescribeJobRequest {
// Discipline id (e.g. 'software_engineering')
string discipline = 1;
// Level id (e.g. 'J060')
string level = 2;
}
These comments produce tool parameters described as "Discipline id (e.g. 'software_engineering')" and "Level id (e.g. 'J060')".
Checklist
-
Config entry uses the
correct
package.Service.Methodpath matching the proto definition - Description is a single sentence that helps agents decide when to use the tool
- Codegen has been run after adding or changing the proto method
-
The tool appears in
npx fit-guide toolsoutput - Proto field comments are descriptive enough for agents to understand each parameter without reading the proto file
Related
- Keep Service Contracts Typed -- the end-to-end workflow for the typed contract libraries including libmcp, libtype, librpc, and libcodegen
-
Codegen Internals -- how
fit-codegendiscovers proto files and generates metadata -
@forwardimpact/libmcpon npm -- installation and changelog