n8n has an [MCP Server Trigger Node](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-langchain.mcptrigger/) that I'm using to play around with local MCP in Claude Code. This is just some basic testing/exploration for MCP integration between Claude Code and n8n. If I were going to use this for meaningful work, I’d put a lot more thought into curating responses and prompting via the tool parameters/descriptions! Below are some notes about my setup, and a couple of configuration changes I made before getting started: - n8n is running locally in a Portainer stack behind a Traefik reverse proxy. I changed the following environment variables in n8n to ensure it gave me the right URLs for the MCP server: ```yaml - N8N_HOST=n8n.home.arpa - WEBHOOK_URL=http://n8n.home.arpa/ - N8N_PROXY_HOPS=1 ``` - I don't have HTTPS set up on Traefik, so in order to allow Claude Code to connect to n8n via HTTP, I set the following environment variable: ```zsh export NODE_TLS_REJECT_UNAUTHORIZED=0 ``` Once those configuration changes were made, I was able to add my workflow as an MCP server to Claude Code. I'm using [PokéAPI](https://pokeapi.co) to test with. Once I had my basic workflow set up, I used this command to add the MCP server to Claude code: ```zsh claude mcp add --transport http pokemon http://n8n.home.arpa/mcp/ ... ``` The first time I connected it, this is all I had in the workflow: ![[Basic MCP server trigger workflow.png]] Here is what the Pokemon Request node looks like: ![[Pokemon Request node.png]] Each of these fields maps to a field that the model sees when invoking the tools. The name of the node (with spaces converted to `_`) becomes the tool name, the description is the tool description, and the "magic" parameters in n8n become the tool parameters for the model. As seen in the screenshot, these are specified in n8n's expression format as follows: ```js {{ $fromAI( 'Pokemon_name', // Parameter name, no spaces 'Name of the Pokemon', // Description 'string', // Type 'ditto' // Default value ) }} ``` When entering a Claude Code session after adding the MCP server, the server and its tools are enabled by default. This can be changed using the `/mcp` command within a Claude Code session. I started testing the workflow by asking Claude to give me some information about Dialga. ``` What can you tell me about Dialga? Use your MCP tools ``` I quickly found out that there is a default maximum token limit of 25,000 tokens for MCP tools in Claude Code. The response for Dialga was 76,670 tokens. ``` Error: MCP tool "Pokemon_Request" response (76670 tokens) exceeds maximum allowed tokens (25000). Please use pagination, filtering, or limit parameters to reduce the response size. ``` For a production workflow, I'd likely turn this HTTP request tool into its own separate workflow or use the built-in "Optimize Response" feature to select individual fields to return in the MCP response. However, this limit can be configured via environment variables (see [MCP output limits and warnings](https://code.claude.com/docs/en/mcp#mcp-output-limits-and-warnings)). I ran this command to set the limit to 100,000 tokens for the purposes of this testing. ```zsh export MAX_MCP_OUTPUT_TOKENS=100000 ``` It's worth noting that Claude Code will warn you when it receives a large response back from an MCP server. ``` ⚠ Large MCP response (~50.7k tokens), this can fill up context quickly ``` Anthropic publishes the rest of the available environment variables, as well as the many settings you can change via JSON configs on their [Claude Code Settings](https://code.claude.com/docs/en/settings) page. This page also lists the tools that Claude Code has by default. [Plugins](https://code.claude.com/docs/en/plugins-reference) sound like an interesting way to standardize a set of configurations or features across a user base. For example, plugins can include MCP server connections, pre- and post-tool hooks, agents, skills, slash commands, and more. A plugin is basically just a collection of configuration files, and potentially scripts for hooks.