Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
41a20bc
feat: first implementation of mcp building based on npm pkgs
FedericoAmura Jul 2, 2025
9cda182
feat: first implementation of mcp building based on npm pkgs - mcp sd…
FedericoAmura Jul 2, 2025
b24254d
feat: servers graceful shutdown, json and registry definitions consol…
FedericoAmura Jul 3, 2025
4774cea
feat: deleted app or tool checks and not prod notification
FedericoAmura Jul 4, 2025
3e8d8cf
fix: remove unused pkgs in mcp-sdk
FedericoAmura Jul 4, 2025
10a1052
feat: use pnpm locally for tools pkg install but npm for out-in-the-w…
FedericoAmura Jul 4, 2025
4ccb43a
feat: comment on require vs import
FedericoAmura Jul 4, 2025
b6f7368
Merge branch 'refs/heads/main' into feature/drel-817-migrate-mcp-from…
FedericoAmura Jul 4, 2025
c1e3897
fix: remove old version plan
FedericoAmura Jul 4, 2025
8c16a12
feat: move tool pkgs installation to server start and away from first…
FedericoAmura Jul 4, 2025
a6d838a
fix: incorrect bundled vincent tool destructuring
FedericoAmura Jul 4, 2025
2480c2c
fix: move which types dev dependency
FedericoAmura Jul 4, 2025
72221c4
chore: code documentation
FedericoAmura Jul 4, 2025
5ce2a6d
chore: doc and readme updates
FedericoAmura Jul 4, 2025
1f620fd
chore: add release plan
FedericoAmura Jul 4, 2025
74da7c6
feat: add descriptions exposed by tools
FedericoAmura Jul 7, 2025
e168934
Merge branch 'main' into feature/drel-817-migrate-mcp-from-ipfc-cids-…
FedericoAmura Jul 9, 2025
b374d76
Merge branch 'main' into feature/drel-817-migrate-mcp-from-ipfc-cids-…
FedericoAmura Jul 9, 2025
2ec989c
fix: use once to call graceful shutdown function
FedericoAmura Jul 9, 2025
de34b8c
feat: convert parameters array in app def json into an object
FedericoAmura Jul 9, 2025
1b1ea11
Merge branch 'refs/heads/main' into feature/drel-817-migrate-mcp-from…
FedericoAmura Jul 10, 2025
6102180
feat: migrate from npm and pnpm to npx-import
FedericoAmura Jul 10, 2025
5e70421
fix: move tools sdk as prod dep in mcp server
FedericoAmura Jul 10, 2025
3a56bcb
Merge branch 'refs/heads/main' into feature/drel-817-migrate-mcp-from…
FedericoAmura Jul 10, 2025
bd08339
feat: use registry sdk and allow for version input as env variable
FedericoAmura Jul 10, 2025
5bcd28f
feat: require mcp-sdk receives vincent bundled tools in its app defin…
FedericoAmura Jul 11, 2025
577ecdb
feat: move tools sdk in mcp sdk to dev dep
FedericoAmura Jul 11, 2025
4e84739
chore: update docs
FedericoAmura Jul 11, 2025
a5680f6
chore: comments updates
FedericoAmura Jul 11, 2025
eccf6ed
fix: set exitCode instead of forcefully exiting
FedericoAmura Jul 11, 2025
5303ce0
feat: just warn and skip on registry deleted tools
FedericoAmura Jul 11, 2025
b298aeb
feat: app version enabled check
FedericoAmura Jul 11, 2025
1a6d82f
feat: app tool in json file exists in registry
FedericoAmura Jul 11, 2025
c49d29f
feat: harden tool failure check
FedericoAmura Jul 11, 2025
bc57d89
fix: make tool params describe override non-mutative on the vincent tool
FedericoAmura Jul 11, 2025
02d8822
fix: removed tools sdk from the wrong package json file
FedericoAmura Jul 11, 2025
99e2d6d
feat: separate env verifications for stdio and http execution making …
FedericoAmura Jul 13, 2025
a9040ab
feat: migrate nonce and transport managers to node-cache
FedericoAmura Jul 13, 2025
58d1109
Merge branch 'main' into feature/drel-817-migrate-mcp-from-ipfc-cids-…
FedericoAmura Jul 13, 2025
5033694
chore: update lockfile
FedericoAmura Jul 13, 2025
51f1340
feat: migrate to the registerTool syntax and add getters also as reso…
FedericoAmura Jul 14, 2025
70d6bac
feat: close transport and nonce managers on http server cleanup
FedericoAmura Jul 14, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .nx/version-plans/version-plan-1751658342657.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
app-sdk: minor
mcp-sdk: major
mcp: major
---

Migration of MCP building from JSON file exclusively to Registry based with json available for overrides
34 changes: 17 additions & 17 deletions docs/src/Developers/App-Agent-Developers/MCP.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ title: MCP - Model Context Protocol

Any Vincent App can be converted into a Model Protocol Server (MCP) that can be consumed by any Large Language Model (LLM) with support for the MCP standard.

We provide an [implementation of an MCP Server](https://github.com/LIT-Protocol/Vincent/tree/main/packages/apps/mcp), connectable through STDIO and HTTP transports. You can use it (forking or [using `npx`](https://www.npmjs.com/package/@lit-protocol/vincent-mcp-server)) with your keys and Vincent Apps or you can customize the whole process to make your own Vincent MCP Server.
We provide an [implementation of an MCP Server](https://github.com/LIT-Protocol/Vincent/tree/main/packages/apps/mcp), connectable through STDIO and HTTP transports. You can use it (forking or [using `npx`](https://www.npmjs.com/package/@lit-protocol/vincent-mcp-server)) with your keys and Vincent Apps or you can customize the whole process to make your own Vincent MCP Server based on our [MCP SDK](https://github.com/LIT-Protocol/Vincent/blob/main/packages/libs/mcp-sdk/README.md).

By following this process, your Vincent App tools will be exposed to LLMs as a set of MCP tools. The MCP server can also be extended with custom tools and prompts to suit your specific needs.
By following this process, your Vincent App tools will be exposed to LLMs as a set of MCP tools. The MCP server can also be extended with custom tools and prompts to suit your specific needs or provide extra capabilities around the Vincent Tool ecosystem.

And if you're building an AI application, check out our [OpenAI AgentKit demo](https://github.com/LIT-Protocol/Vincent-MCP-OpenAI-AgentKit) for a guide on how to integrate your Vincent App with the OpenAI AgentKit.

Expand All @@ -20,6 +20,7 @@ The first step is to convert your Vincent App into an MCP server. This is done b
```typescript
import { ethers } from 'ethers';
import { getVincentAppServer, VincentAppDef } from '@lit-protocol/vincent-mcp-sdk';
import { bundledVincentTool } from '@organization/npm-published-vincent-too';

// Create a signer using your Vincent App delegatee private key
const provider = new ethers.providers.JsonRpcProvider(
Expand All @@ -34,18 +35,17 @@ const appDef: VincentAppDef = {
name: 'My Vincent App',
description: 'A Vincent application that executes tools for its delegators',
tools: {
QmIpfsCid1: {
'@organization/npm-published-vincent-tool': {
version: '1.0.0',
bundledVincentTool: bundledVincentTool,
name: 'myTool',
description: 'A tool that does something',
parameters: [
{
name: 'param1',
type: 'string',
parameters: {
param1: {
description: 'A parameter that is used in the tool to do something',
optional: true,
},
// Add more parameters here
],
},
},
// Add the other tools in your Vincent App here
},
Expand All @@ -55,19 +55,17 @@ const appDef: VincentAppDef = {
const server = await getVincentAppServer(wallet, appDef);
```

You can check the [Uniswap Swap example app json](https://github.com/LIT-Protocol/Vincent/blob/main/packages/apps/mcp/vincent-app.example.json) for a complete Vincent App definition.

## Extending the MCP Server

At this moment you can add more tools, resources or prompts to the server.

```typescript
server.tool(...);
server.resource(...);
server.prompt(...);
server.registerTool(/*...*/);
server.registerResource(/*...*/);
server.registerPrompt(/*...*/);
```

These tools, resources and prompts will be exposed in the server along with the ones from the Vincent App definition. Consider adding any other tools that you want to be executed by the LLM and that are not Vincent Tools such as tools to query balance or fetch useful data from external sources.
These tools, resources and prompts will be exposed in the server along with the ones from the Vincent App definition. Consider adding any other tools that you want to be executed by the LLM and that are not Vincent Tools. For example, you could add tools to query balance or fetch useful data from external sources.

## Picking a Transport

Expand Down Expand Up @@ -124,9 +122,11 @@ For an already working MCP Server that simply wraps your Vincent App you can che

This MCP Server includes:

- Running as `npx` commands directly from NPM
- Automatic tool installation using `npx-import`. No local installation needed
- HTTP and STDIO transports
- `.env` file support for environment definition
- App definition with a custom JSON file to define which tools and params are exposed to LLMs
- App definition overriding with a custom JSON file to refine descriptions and filter tools to be exposed to LLMs
- Support for delegatee and delegators in HTTP transport
- Delegators MUST authenticate with SIWE OR their Vincent JWT
- Delegatees MUST identify with SIWE
Expand Down Expand Up @@ -162,7 +162,7 @@ Before deploying, you'll need to create the following two files in the root of y
CMD ["npx", "@lit-protocol/vincent-mcp-server", "http"]
```

2. Create the Vincent App JSON definition file. Fill it with the data of your Vincent: ID, version, name, description and tools data. Check the [Uniswap Swap example app json](https://github.com/LIT-Protocol/Vincent/blob/main/packages/apps/mcp/vincent-app.example.json) for a complete Vincent App definition.
2. Create the Vincent App JSON definition override file. Fill it with the data of your Vincent App you want to override: ID, version, name, description and tools data. Check the [Uniswap Swap example app json](https://github.com/LIT-Protocol/Vincent/blob/main/packages/apps/mcp/vincent-app.example.json) for a complete Vincent App override file.

3. Add both files to git. Commit and push them to your repository to use as source for Heroku or Render.

Expand Down
4 changes: 3 additions & 1 deletion packages/apps/mcp/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,6 @@ VINCENT_MCP_BASE_URL=https://example.com

# Vincent App config
VINCENT_DELEGATEE_PRIVATE_KEY=
VINCENT_APP_JSON_DEFINITION=/your/vincent/app/definitionfile/vincent/packages/apps/mcp/vincent-app.example.json
VINCENT_APP_ID= # Optional if the json file at VINCENT_APP_JSON_DEFINITION includes an "id"
VINCENT_APP_VERSION= # Optional, will default to latest version in Vincent Registry
VINCENT_APP_JSON_DEFINITION=/your/vincent/app/definitionfile/vincent/packages/apps/mcp/vincent-app.example.json # Optional
86 changes: 44 additions & 42 deletions packages/apps/mcp/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,49 +6,45 @@ It leverages the `@lit-protocol/vincent-mcp-sdk` to build a server from a Vincen

## Setup

- Copy `vincent-app.example.json` to `vincent-app.json` or any other name you want and configure your Vincent App definition in it.
- Copy `.env.example` to `.env` and fill in the values. Use absolute paths for the `VINCENT_APP_JSON_DEFINITION` value.
- Optional: Copy `vincent-app.example.json` to `vincent-app.json` or any other name you want and configure your Vincent App definition overrides in it. If no overrides are needed, then this file can be omitted.
- Optional: Copy `.env.example` to `.env` and fill in the values. Use absolute paths for the `VINCENT_APP_JSON_DEFINITION` value. You can also pass them via CLI arguments when calling the script.

# Writing App definition JSON file
# Writing App definition overrides in a JSON file
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we make it clear what the behaviour will be if you define a JSON file and an environment var, and they have different values? Does the JSON file override the .env, or the other way around? Or will the MCP server refuse to start because it can't be sure what to do?


To define the Vincent App that will be transformed into an MCP Server, a JSON definition of it must be provided.
Name and descriptions provided by developers in the registry might not be very descriptive to LLMs or you may want to modify them.

In order to override any of those values, create a `.json` file with the following structure:

```json
{
"id": "8462368", // The Id of the Vincent App
"version": "1", // The version of the Vincent App
"name": "My Vincent App", // Name of the Vincent App. Can be overriden, doesn't have to be the same as in the registry.
"description": "A Vincent application that executes tools for its delegators", // Description of the Vincent App. Can be overriden, doesn't have to be the same as in the registry.
// Adding a tools object will override what is already present in the registry. Without this field, all tools from the registry will be exposed.
"tools": {
// Any tool that you want to expose to the LLM has to be included using its IPFS CID as key in this object. If a tool is not included, it is not exposed as an MCP Server tool.
"QmIpfsCid1": {
"name": "myTool", // Name of the tool. Can be overriden, doesn't have to be the same as in the registry.
"description": "A tool that does something", // Description of the tool. Can be overriden, doesn't have to be the same as in the registry.
// All parameters of the tool have to be added under this array or the LLM won't be able to see them or provide values for it
"parameters": [
{
"name": "param1", // Name of the param. Cannot be overriden.
"type": "string", // Type of the param. Must be the type the tool expects.
"description": "A parameter that is used in the tool to do something" // Description of the param. Can be overriden.
// Any tool that you want to expose to the LLM has to be included using its NPM package name as key in this object. If a tool is not included, it is not exposed as an MCP Server tool.
"vincent-tool-npm-pkg-name": {
"name": "myTool", // Name of the tool. Defaults to npm pkg name.
"description": "A tool that does something", // Description of the tool.
"parameters": {
// Keys are the names of each param. Used to identify and apply the rest of properties.
"param1": {
"description": "A parameter that is used in the tool to do something" // Description of the param.
}
// ...rest of params you want to expose.
// Any optional param that is not included here will be exposed by the tool.
]
}
// ...rest of params you want to override.
}
},
"vincent-tool-without-overrides": {} // Empty objects mean that the tool is exposed but with default values.
}
}
```

For any value that can be overriden, consider that those are the hints the LLM uses to know how to use the tool. Therefore, those are good places to provide any information you want the LLM to know about the tool such as units, formats, examples or pre-conditions to check.

If you are the owner of the app, most of the data can be obtained from the Vincent App page in the Vincent dashboard.
When the `tools` property is omitted, all tools from the registry will be exposed. When overriding at least one tool, you need to specify all others that you want to still expose as MCP tools, even with empty values inside.

If you are not the owner of the app, the tool fields and its included tools IPFS CIDs are shown in the consent screen.

The IPFS CID can also be obtained from the bundled tool code published in npm. For example [vincent-tool-metadata.json](../tool-erc20-approval/src/generated/vincent-tool-metadata.json) for our ERC20 approval tool.
To get the tool params from source code, you can check the tool schemas such as [schemas.ts](../tool-erc20-approval/src/lib/schemas.ts) for our ERC20 approval tool.
For any value that can be overriden, consider that those are the hints the LLM uses to know how to use the tool. Therefore, those are good places to provide any information you want the LLM to know about the tool such as units, formats, examples or pre-conditions to check.

Any tool created using our [Tools and Policies SDK](https://www.npmjs.com/package/@lit-protocol/vincent-tool-sdk) will provide those files.
Tools included in definition MUST be published in NPM and imported using their package names. Also, they must be part of the Vincent App and recorded in the Vincent Registry. Any tool that is not part of that specific app will fail its invocation.

# Running

Expand All @@ -66,10 +62,14 @@ You can run the Vincent MCP server directly using npx without downloading the re
npx @lit-protocol/vincent-mcp-server stdio
```

When setting this in the LLM client, pass it the necessary environment variables from your client. These env variables include:
When setting this in the LLM client, pass it the necessary environment variables from your LLM client. These env variables include:

- `VINCENT_APP_JSON_DEFINITION`: Path to your Vincent App definition JSON file
- `VINCENT_DELEGATEE_PRIVATE_KEY`: The private key of the delegatee. This is the one you added in the Vincent App Dashboard as [an authorized signer for your app](https://docs.heyvincent.ai/documents/Quick_Start.html#:~:text=New%20App%22%20button.-,Delegatees,-%3A%20Delegatees%20are). This private key MUST be an allowed delegatee of the Vincent App defined in the JSON.
- `VINCENT_DELEGATEE_PRIVATE_KEY`: The private key of the delegatee. This is the one you added in the Vincent App Dashboard as [an authorized signer for your app](https://docs.heyvincent.ai/documents/Quick_Start.html#:~:text=New%20App%22%20button.-,Delegatees,-%3A%20Delegatees%20are). This private key MUST be an allowed delegatee of the Vincent App.
- (Optional) `VINCENT_APP_ID`: The Vincent App Id you want to run as an MCP Server
- (Optional) `VINCENT_APP_VERSION`: The Vincent App Version you want to run as an MCP Server
- (Optional) `VINCENT_APP_JSON_DEFINITION`: Path to your Vincent App overrides JSON file

Note: The environment MUST include the Vincent App Id, either via the `VINCENT_APP_ID` env variable or in the App definition JSON file. The version is completely optional as it will default to the latest version specified in the registry.

### HTTP mode

Expand All @@ -79,28 +79,30 @@ npx @lit-protocol/vincent-mcp-server http

In HTTP mode, the environment variables are configured on the server itself, not the client running it.

These commands require the following environment variables to be set:
To configure runtime environment in this mode, set the following environment variables:

- `VINCENT_DELEGATEE_PRIVATE_KEY`: The private key of the delegatee. This is the one you added in the Vincent App Dashboard as [an authorized signer for your app](https://docs.heyvincent.ai/documents/Quick_Start.html#:~:text=New%20App%22%20button.-,Delegatees,-%3A%20Delegatees%20are). This private key MUST be an allowed delegatee of the Vincent App.
- (Optional) `VINCENT_APP_ID`: The Vincent App Id you want to run as an MCP Server
- (Optional) `VINCENT_APP_VERSION`: The Vincent App Version you want to run as an MCP Server
- (Optional) `VINCENT_APP_JSON_DEFINITION`: Path to your Vincent App overrides JSON file
- `EXPECTED_AUDIENCE`: The audience that you expect JWTs to have. Vincent populates this with the redirect URLs. Likely you want this server to be one of those URLs.
- `VINCENT_APP_JSON_DEFINITION`: Path to your Vincent App definition JSON file
- `VINCENT_DELEGATEE_PRIVATE_KEY`: The private key of the delegatee. This is the one you added in the Vincent App Dashboard as [an authorized signer for your app](https://docs.heyvincent.ai/documents/Quick_Start.html#:~:text=New%20App%22%20button.-,Delegatees,-%3A%20Delegatees%20are).
- `VINCENT_MCP_BASE_URL`: This MCP server URL
- `PORT` (for HTTP mode only): The port to run the HTTP server on (defaults to 3000)

Other optional environment variables include:
- `VINCENT_MCP_BASE_URL`: This MCP server URL. Used to generate SIWE messages and verify signatures
- `VINCENT_REGISTRY_URL`: This Vincent Registry server URL. Will be queried to get the Vincent App and its tools info
- (Optional) `PORT`: The port to run the HTTP server on (defaults to 3000)
- (Optional) `HTTP_TRANSPORT_CLEAN_INTERVAL`: Defines the interval (milliseconds) that the server will use to clean unused transports. Defaults to 1 hour
- (Optional) `HTTP_TRANSPORT_TTL`: Defines the time (milliseconds) that a transport will still be considered in use after the last time it was actually used. Defaults to 1 hour
- (Optional) `SIWE_EXPIRATION_TIME`: Duration of the generated SIWE message to sign. Defaults to 1 hour
- (Optional) `SIWE_NONCE_CLEAN_INTERVAL`: Defines the interval (milliseconds) that the server will use to clean unused transports. Defaults to 1 hour
- (Optional) `SIWE_NONCE_TTL`: Defines the time (milliseconds) that a SIWE nonce will still be considered valid after it was created. Defaults to 5 minutes

- `HTTP_TRANSPORT_CLEAN_INTERVAL`: Defines the interval (milliseconds) that the server will use to clean unused transports. Defaults to 1 hour
- `HTTP_TRANSPORT_TTL`: Defines the time (milliseconds) that a transport will still be considered in use after the last time it was actually used. Defaults to 1 hour
- `SIWE_EXPIRATION_TIME`: Duration of the generated SIWE message to sign. Defaults to 1 hour
- `SIWE_NONCE_CLEAN_INTERVAL`: Defines the interval (milliseconds) that the server will use to clean unused transports. Defaults to 1 hour
- `SIWE_NONCE_TTL`: Defines the time (milliseconds) that a SIWE nonce will still be considered valid after it was created. Defaults to 5 minutes
Note: The environment MUST include the Vincent App Id, either via the `VINCENT_APP_ID` env variable or in the App definition JSON file. The version is completely optional as it will default to the latest version specified in the registry.

Consider that a SIWE message must have a valid nonce, so it will become invalid after reaching the expiration time or the nonce has been discarded.

You can set these environment variables in your shell before running the commands, or use a tool like `dotenvx`:

```bash
dotenvx run -f /path/to/.env -- npx @lit-protocol/vincent-mcp-server http
dotenvx run -f /path/to/.env -- npx -y @lit-protocol/vincent-mcp-server http
```

For an .env file example check [./.env.example](./.env.example)
Expand Down
5 changes: 5 additions & 0 deletions packages/apps/mcp/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,17 +29,22 @@
"main": "./dist/src/bin/cli.js",
"scripts": {
"dev:http": "tsx watch --tsconfig ./tsconfig.app.json --env-file=.env src/bin/http.ts",
"dev:stdio": "tsx watch --tsconfig ./tsconfig.app.json --env-file=.env src/bin/stdio.ts",
"inspector": "npx @modelcontextprotocol/inspector"
},
"dependencies": {
"@lit-protocol/constants": "^7.1.1",
"@lit-protocol/vincent-app-sdk": "workspace:*",
"@lit-protocol/vincent-mcp-sdk": "workspace:*",
"@lit-protocol/vincent-registry-sdk": "workspace:*",
"@modelcontextprotocol/sdk": "^1.12.1",
"@reduxjs/toolkit": "^2.8.2",
"@t3-oss/env-core": "^0.13.4",
"cors": "^2.8.5",
"ethers": "^5.8.0",
"express": "^5.1.0",
"node-cache": "^5.1.2",
"npx-import": "^1.1.4",
"siwe": "^3.0.0",
"tslib": "^2.8.1",
"zod": "^3.25.64"
Expand Down
Loading
Loading