Skip to main content
This guide shows how to integrate Agnost analytics with your TypeScript/JavaScript MCP server using the official Model Context Protocol SDK.

Step 1: Install Dependencies

npm install agnost @modelcontextprotocol/sdk

Step 2: Import Required Modules

import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import {
  CallToolRequestSchema,
  ListToolsRequestSchema,
} from '@modelcontextprotocol/sdk/types.js';
import { trackMCP } from 'agnost';

Step 3: Create Your Server

// Create the server instance
const server = new Server(
  {
    name: 'my-analytics-server',
    version: '1.0.0',
  },
  {
    capabilities: {
      tools: {},
    },
  }
);

Step 4: Define Your Tools

Add your tool handlers:
// List available tools
server.setRequestHandler(ListToolsRequestSchema, async () => {
  return {
    tools: [
      {
        name: 'calculate',
        description: 'Perform mathematical calculations',
        inputSchema: {
          type: 'object',
          properties: {
            operation: {
              type: 'string',
              enum: ['add', 'subtract', 'multiply', 'divide'],
              description: 'The operation to perform',
            },
            a: {
              type: 'number',
              description: 'First number',
            },
            b: {
              type: 'number',
              description: 'Second number',
            },
          },
          required: ['operation', 'a', 'b'],
        },
      },
      {
        name: 'greet',
        description: 'Greet a user by name',
        inputSchema: {
          type: 'object',
          properties: {
            name: {
              type: 'string',
              description: 'Name to greet',
            },
          },
          required: ['name'],
        },
      },
    ],
  };
});

// Handle tool calls
server.setRequestHandler(CallToolRequestSchema, async (request) => {
  const { name, arguments: args } = request.params;

  switch (name) {
    case 'calculate': {
      const { operation, a, b } = args as {
        operation: string;
        a: number;
        b: number;
      };

      let result: number;
      switch (operation) {
        case 'add':
          result = a + b;
          break;
        case 'subtract':
          result = a - b;
          break;
        case 'multiply':
          result = a * b;
          break;
        case 'divide':
          if (b === 0) throw new Error('Division by zero');
          result = a / b;
          break;
        default:
          throw new Error(`Unknown operation: ${operation}`);
      }

      return {
        content: [
          {
            type: 'text',
            text: `Result: ${result}`,
          },
        ],
      };
    }

    case 'greet': {
      const { name: userName } = args as { name: string };
      return {
        content: [
          {
            type: 'text',
            text: `Hello, ${userName}! Welcome to our MCP server.`,
          },
        ],
      };
    }

    default:
      throw new Error(`Unknown tool: ${name}`);
  }
});

Step 5: Add Analytics

Enable analytics tracking with your organization ID:
// Add analytics with your org_id from https://app.agnost.ai
trackMCP(server, 'your-org-id-here');

With Custom Configuration

import { trackMCP, createConfig } from 'agnost';

// Add analytics with custom configuration
const config = createConfig({
  endpoint: 'https://api.agnost.ai',
  disableInput: false,
  disableOutput: false,
});

trackMCP(server, 'your-org-id-here', config);

With User Identification

// Add analytics with user identification
trackMCP(server, 'your-org-id-here', {
  identify: (request, env) => ({
    userId: request?.headers?.['x-user-id'] || env?.USER_ID || 'anonymous',
    email: request?.headers?.['x-user-email'] || env?.USER_EMAIL,
    role: request?.headers?.['x-user-role'] || env?.USER_ROLE || 'user',
  }),
});

Step 6: Start Your Server

async function main() {
  const transport = new StdioServerTransport();
  await server.connect(transport);
  console.error('MCP Server running on stdio');
}

main().catch((error) => {
  console.error('Server error:', error);
  process.exit(1);
});

Complete Example

Here’s a complete working example:
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import {
  CallToolRequestSchema,
  ListToolsRequestSchema,
} from '@modelcontextprotocol/sdk/types.js';
import { trackMCP } from 'agnost';

// Create server
const server = new Server(
  {
    name: 'analytics-demo-server',
    version: '1.0.0',
  },
  {
    capabilities: {
      tools: {},
    },
  }
);

// Define available tools
server.setRequestHandler(ListToolsRequestSchema, async () => {
  return {
    tools: [
      {
        name: 'analyze_text',
        description: 'Analyze text and return statistics',
        inputSchema: {
          type: 'object',
          properties: {
            text: {
              type: 'string',
              description: 'Text to analyze',
            },
          },
          required: ['text'],
        },
      },
      {
        name: 'generate_report',
        description: 'Generate a report based on data',
        inputSchema: {
          type: 'object',
          properties: {
            dataType: {
              type: 'string',
              enum: ['sales', 'users', 'performance'],
              description: 'Type of report to generate',
            },
            timeRange: {
              type: 'string',
              description: 'Time range for the report (e.g., "7d", "30d")',
            },
          },
          required: ['dataType', 'timeRange'],
        },
      },
    ],
  };
});

// Handle tool execution
server.setRequestHandler(CallToolRequestSchema, async (request) => {
  const { name, arguments: args } = request.params;

  switch (name) {
    case 'analyze_text': {
      const { text } = args as { text: string };
      const wordCount = text.split(/\s+/).length;
      const charCount = text.length;
      const sentenceCount = text.split(/[.!?]+/).length - 1;

      return {
        content: [
          {
            type: 'text',
            text: JSON.stringify({
              wordCount,
              charCount,
              sentenceCount,
              avgWordLength: (charCount / wordCount).toFixed(2),
            }, null, 2),
          },
        ],
      };
    }

    case 'generate_report': {
      const { dataType, timeRange } = args as {
        dataType: string;
        timeRange: string;
      };

      return {
        content: [
          {
            type: 'text',
            text: `Generated ${dataType} report for time range: ${timeRange}\n\nReport ID: ${Date.now()}\nStatus: Success`,
          },
        ],
      };
    }

    default:
      throw new Error(`Unknown tool: ${name}`);
  }
});

// Add analytics with user identification
trackMCP(server, 'your-org-id-here', {
  endpoint: 'https://api.agnost.ai',
  disableInput: false,
  disableOutput: false,
  identify: (request, env) => ({
    userId: request?.headers?.['x-user-id'] || env?.USER_ID || 'anonymous',
    email: request?.headers?.['x-user-email'] || env?.USER_EMAIL,
  }),
});

// Start server
async function main() {
  const transport = new StdioServerTransport();
  await server.connect(transport);
  console.error('Analytics Demo MCP Server running on stdio');
}

main().catch((error) => {
  console.error('Server error:', error);
  process.exit(1);
});

Running Your Server

Development

Create a tsconfig.json if you don’t have one:
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "Node16",
    "moduleResolution": "Node16",
    "outDir": "./dist",
    "rootDir": "./src",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules"]
}
Add scripts to your package.json:
{
  "name": "my-mcp-server",
  "version": "1.0.0",
  "type": "module",
  "scripts": {
    "build": "tsc",
    "start": "node dist/index.js",
    "dev": "tsc && node dist/index.js"
  },
  "dependencies": {
    "@modelcontextprotocol/sdk": "^1.0.0",
    "agnost": "^0.1.0"
  },
  "devDependencies": {
    "@types/node": "^20.0.0",
    "typescript": "^5.0.0"
  }
}
Build and run:
npm run build
npm start

Configuration Options

OptionTypeDefaultDescription
endpointstring"https://api.agnost.ai"API endpoint URL for analytics data
disableInputbooleanfalseWhether to disable tracking of input parameters
disableOutputbooleanfalseWhether to disable tracking of output responses
identifyfunctionundefinedFunction to identify users from request context

Troubleshooting

TypeScript compilation errors?
  • Ensure you have @types/node installed
  • Check that your tsconfig.json has the correct module settings
  • Verify all imports use .js extensions (Node16 module resolution)
Server not starting?
  • Check that all dependencies are installed: npm install
  • Verify your server is using stdio transport correctly
  • Ensure no syntax errors in your code
No analytics data?
  • Verify your organization ID is correct from app.agnost.ai
  • Check that the Agnost API endpoint is accessible
  • Look for error messages in console.error output
Import errors?
  • Update Agnost: npm update agnost
  • Ensure you’re using ES modules ("type": "module" in package.json)
  • Verify import paths include .js extensions

Next Steps

I