# How MCP Works

import Code from '~/components/Code/Code.astro'

The Azion MCP server operates as a bridge between AI assistants and the Azion Platform, providing secure access to documentation, tools, and resources through a standardized protocol.

---

## Technical Architecture

MCP implements a client-server model using Anthropic's Model Context Protocol. The architecture consists of three main components:

### Technology Stack

| Component | Technology | Purpose |
|------------|------------|-----------|
| **Runtime** | Node.js 20+ | JavaScript execution environment |
| **Language** | TypeScript | Static typing and safety |
| **Protocol** | MCP SDK | Anthropic protocol implementation |
| **Hosting** | Functions | Distributed execution on Azion |
| **Authentication** | Personal Token / OAuth | Secure access control |

### Communication Flow

```text
AI Assistant (Client)
    ↓ HTTP/WebSocket Connection
MCP Server (Function)
    ↓ API Calls
Azion Platform (Resources)
```

The flow works as follows:

1. **Connection**: The MCP client establishes connection with the server using HTTP or WebSocket
2. **Authentication**: The Personal Token validates the user's identity
3. **Discovery**: The client discovers available tools and resources
4. **Execution**: The assistant invokes tools as needed
5. **Response**: The server returns structured data to the client

---

## MCP Components

The MCP protocol defines three main types of capabilities that a server can expose:

### Tools

Tools are functions that the AI assistant can invoke to perform actions or fetch information. Each tool has:

- **Name**: Unique identifier (e.g., `search_azion_docs_and_site`)
- **Description**: Explains the purpose and when to use it
- **Input Schema**: Defines expected parameters using JSON Schema
- **Handler**: Function that executes the logic

Example tool definition:

<Code lang="typescript" code={`server.tool(
  'search_azion_docs_and_site',
  {
    description: 'Provides information about Azion Platform, products, and services',
    inputSchema: {
      type: 'object',
      properties: {
        query: {
          type: 'string',
          description: 'Query to search documentation'
        },
        docsAmount: {
          type: 'number',
          description: 'Number of documents to return',
          default: 5
        }
      },
      required: ['query']
    }
  },
  async (args) => {
    // Search implementation
    const results = await searchDocs(args.query, args.docsAmount);
    return {
      content: [{
        type: 'text',
        text: JSON.stringify(results)
      }]
    };
  }
);`} />

### Resources

Resources are structured data that can be read by the client, similar to files. They use URIs for identification:

<Code lang="typescript" code={`server.resource(
  'static-site-deploy-guide',
  'azion://static-site/deploy/step-0-preparation',
  async () => ({
    contents: [{
      uri: 'azion://static-site/deploy/step-0-preparation',
      name: 'step-0-preparation.md',
      mimeType: 'text/markdown',
      text: guideContent
    }]
  })
);`} />

Resource URIs follow the format: `azion://[category]/[resource]/[item]`

### Prompts

Prompts are pre-configured templates that help with common scenarios:

<Code lang="typescript" code={`server.prompt(
  'deploy-static-site',
  {
    description: 'Step-by-step guide for deploying static sites',
    arguments: [
      {
        name: 'framework',
        description: 'Framework used (e.g., nextjs, astro, hugo)',
        required: true
      }
    ]
  },
  async (args) => {
    return {
      messages: [{
        role: 'user',
        content: {
          type: 'text',
          text: 'Help me deploy a ' + args.framework + ' site to Azion'
        }
      }]
    };
  }
);`} />

---

## Implementing an MCP Server

To implement your own MCP server, follow these steps:

### Project Structure

<Code lang="text" code={`my-mcp-server/
├── src/
│   ├── index.ts           # Entry point
│   ├── core/
│   │   ├── tools.ts       # Tool definitions
│   │   ├── resources.ts   # Resource definitions
│   │   ├── prompts.ts     # Prompt definitions
│   │   └── services/      # Business logic
│   └── middlewares/
│       └── auth.ts        # Authentication
├── package.json
├── tsconfig.json
└── azion.config.ts        # Deploy configuration`} />

### Entry Point

The main file initializes the server and registers capabilities:

<Code lang="typescript" code={`// src/index.ts
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { registerTools } from './core/tools';
import { registerResources } from './core/resources';
import { registerPrompts } from './core/prompts';

const server = new McpServer({
  name: 'my-mcp-server',
  version: '1.0.0'
});

// Register capabilities
registerTools(server);
registerResources(server);
registerPrompts(server);

// Start server
export default {
  async fetch(request: Request): Promise<Response> {
    return server.handleRequest(request);
  }
};`} />

### Authentication

The MCP server supports multiple authentication methods:

<Code lang="typescript" code={`// src/middlewares/auth.ts
export async function authenticate(request: Request): Promise<AuthResult> {
  const authHeader = request.headers.get('Authorization');
  
  if (!authHeader) {
    return { success: false, error: 'Token not provided' };
  }

  const token = authHeader.replace('Bearer ', '');

  // Verify Personal Token (format: azion + 35 chars)
  if (token.startsWith('azion') && token.length === 40) {
    return validatePersonalToken(token);
  }

  // Verify OAuth token via SSO
  return validateOAuthToken(token);
}`} />

---

## Deploying to Azion

The MCP server can be deployed as a Function on Azion:

### Configuration

Create an `azion.config.ts` file in the project root:

```
// azion.config.ts
export default {
  build: {
    preset: 'typescript',
    polyfills: true
  },
  functions: [
    {
      name: '$FUNCTION_NAME',
      path: './functions/index.js'
    }
  ],
  applications: [
    {
      name: '$APPLICATION_NAME',
      rules: {
        request: [
          {
            name: 'Execute Function',
            description: 'Execute function for all requests',
            active: true,
            criteria: [
              [
                {
                  variable: '${uri}',
                  conditional: 'if',
                  operator: 'matches',
                  argument: '^/'
                }
              ]
            ],
            behaviors: [
              {
                type: 'run_function',
                attributes: {
                  value: '$FUNCTION_NAME'
                }
              }
            ]
          }
        ]
      },
      functionsInstances: [
        {
          name: '$FUNCTION_INSTANCE_NAME',
          ref: '$FUNCTION_NAME'
        }
      ]
    }
  ],
  workloads: [
    {
      name: '$WORKLOAD_NAME',
      active: true,
      infrastructure: 1,
      deployments: [
        {
          name: '$DEPLOYMENT_NAME',
          current: true,
          active: true,
          strategy: {
            type: 'default',
            attributes: {
              application: '$APPLICATION_NAME'
            }
          }
        }
      ]
    }
  ]
}
```

### Deploy

Use the Azion CLI to deploy:

<Code lang="bash" code={`# Link project
azion link

# Build project
azion build

# Deploy to production
azion deploy`} />

The deploy creates a publicly accessible URL that can be configured in MCP clients.

---

## Best Practices

### Tool Design

1. **Descriptive names**: Use clear verbs and nouns (e.g., `search_docs`, `create_rule`)
2. **Typed parameters**: Define complete JSON Schema schemas
3. **Clear descriptions**: Explain when and how to use each tool
4. **Error handling**: Return informative error messages
5. **Idempotency**: Tools should be safe for multiple calls

### Performance

1. **Response caching**: Implement cache for frequently accessed data
2. **Pagination**: Use pagination for large datasets
3. **Timeouts**: Set appropriate timeouts for long operations
4. **Compression**: Compress large responses

### Security

1. **Input validation**: Always validate input parameters
2. **Rate limiting**: Implement rate limits per token
3. **Audit logs**: Log all sensitive operations
4. **Sanitization**: Remove sensitive data before returning

---

## Complete Example

See a complete example of a documentation search tool:

<Code lang="typescript" code={`// src/core/services/docsService.ts
import { z } from 'zod';

const SearchSchema = z.object({
  query: z.string().min(1),
  docsAmount: z.number().min(1).max(20).default(5)
});

export async function searchDocumentation(args: unknown) {
  // Validate input
  const validated = SearchSchema.parse(args);
  
  // Search documents
  const response = await fetch('https://api.azion.com/docs/search', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': 'Bearer ' + process.env.AZION_API_KEY
    },
    body: JSON.stringify({
      query: validated.query,
      limit: validated.docsAmount
    })
  });

  if (!response.ok) {
    throw new Error('Search failed: ' + response.statusText);
  }

  const results = await response.json();
  
  // Format response
  return {
    content: [{
      type: 'text',
      text: JSON.stringify(results, null, 2)
    }]
  };
}`} />

---

## Additional Resources

- [MCP Specification](https://modelcontextprotocol.io) - Official protocol documentation
- [MCP SDK](https://github.com/modelcontextprotocol/typescript-sdk) - Official TypeScript SDK
- [Azion MCP Repository](https://github.com/aziontech/mcp-server/
) - Azion server source code
- [MCP Overview](/en/documentation/devtools/mcp/) - Introduction to MCP
- [Configuration Guide](/en/documentation/devtools/mcp/configuration/) - Set up your environment
- [Practical Examples](/en/documentation/devtools/mcp/examples/) - Real-world use cases