Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
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
6 changes: 6 additions & 0 deletions .claude/settings.local.json

Choose a reason for hiding this comment

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

I think we shouldn't commit local settings...

Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"permissions": {
"allow": ["Bash(npm run build:*)", "Bash(npm ci:*)"],
"deny": []
}
}
186 changes: 186 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Essential Commands

### Development Commands
```bash
# Install dependencies
npm ci

# Build the project (TypeScript compilation)
npm run build

# Start development server with auto-reload (no build required)
npm run dev:stdio # For STDIO transport
npm run dev:sse # For SSE transport
npm run dev:shttp # For Streamable HTTP transport

# Start production server (requires build)
npm run start:stdio # For STDIO transport
npm run start:sse # For SSE transport
npm run start:shttp # For Streamable HTTP transport
```

### Code Quality Commands
```bash
# Run formatter and linter check
npm run format

# Auto-fix formatting and linting issues
npm run format:fix
```

### Debugging
```bash
# Debug with MCP inspector
npx @modelcontextprotocol/inspector -e KONTENT_API_KEY=<key> -e KONTENT_ENVIRONMENT_ID=<env-id> node build/bin.js

# Or inspect a running SSE server
npx @modelcontextprotocol/inspector
```

## Architecture Overview

This is a Model Context Protocol (MCP) server for Kontent.ai that enables AI models to interact with Kontent.ai's APIs through natural language. The project follows a modular architecture:

### Core Components

1. **Transport Layer** (`src/bin.ts`): Single entry point supporting three transport protocols:
- STDIO: Direct process communication
- SSE (Server-Sent Events): HTTP-based real-time communication
- Streamable HTTP: Request-response based HTTP communication

2. **Server Core** (`src/server.ts`): Central server instance that:
- Registers all available tools
- Manages MCP server lifecycle
- Coordinates tool execution

3. **Tools Directory** (`src/tools/`): Each tool is a separate module that:
- Implements a specific Kontent.ai operation
- Uses standardized error handling via `errorHandler.ts`
- Returns responses using `createMcpToolSuccessResponse`
- Must call `get-initial-context` before any other operation

4. **API Clients** (`src/clients/kontentClients.ts`): Manages Kontent.ai SDK instances:
- Management API client for content operations
- Delivery API client for read-only content access
- Includes source tracking headers for API usage analytics

5. **Validation Schemas** (`src/schemas/`): Zod schemas for input validation:
- Content item, content type, taxonomy schemas
- Specialized patch operation schemas
- Workflow and variant filtering schemas

### Critical Development Rules

#### Tool Naming Conventions
Tools follow strict naming patterns enforced by Cursor rules:
- **Names must be under 35 characters** (enforced in `.cursor/rules/mcp-tool-naming.mdc`)
- Format: `[action]-[entity]-[api-suffix]`
- API suffixes: `-mapi` (Management API), `-dapi` (Delivery API)
- Example: `get-content-type-mapi`, `filter-variants-mapi`

#### Tool Descriptions
Tool descriptions must follow a standardized pattern (enforced in `.cursor/rules/kontent-tool-descriptions.mdc`):
- Pattern: `"[Action] [Kontent.ai entity] [method/context] [API source]"`
- **Always include "Kontent.ai"** explicitly
- **Always specify the API source**
- Example: "Get Kontent.ai content type by internal ID from Management API"

#### README Synchronization
When modifying tools (enforced in `.cursor/rules/tools-in-readme.mdc`):
- **Adding tools**: Always describe them in README.md
- **Modifying tools**: Adjust descriptions in README.md accordingly
- **Removing tools**: Remove all mentions from README.md
- **Table of Contents**: Must contain only second-level headings (enforced in `.cursor/rules/toc-readme.mdc`)

### Environment Requirements

Required environment variables:
- `KONTENT_API_KEY`: Management API key
- `KONTENT_ENVIRONMENT_ID`: Environment ID
- `PORT`: Server port (optional, defaults to 3001)

### Code Style

- TypeScript with ES2022 target, NodeNext modules
- Biome for formatting and linting (configuration in `biome.json`)
- Double quotes for strings
- 2-space indentation
- Strict TypeScript mode enabled
- Organize imports on save

### Key Implementation Patterns

#### 1. Tool Registration Pattern
Each tool follows this structure:
```typescript
export const registerTool = (server: McpServer): void => {
server.tool(
"tool-name", // Under 35 characters
"Tool description", // Following the pattern
{ /* Zod schema for parameters */ },
async (params) => {
const client = createMapiClient();
try {
// Implementation
return createMcpToolSuccessResponse(response);
} catch (error) {
return handleMcpToolError(error, "Context");
}
}
);
};
```

#### 2. Error Handling
The `errorHandler.ts` provides standardized error handling:
- Handles Kontent.ai Management API specific errors
- Includes validation error details
- Provides consistent error response format
- Preserves request IDs for debugging

#### 3. Patch Operations
Content type modifications use JSON Patch operations:
- **move**: Move elements within content type (uses path references like `/elements/id:{uuid}`)
- **addInto**: Add new elements to content type
- **remove**: Remove elements from content type
- **replace**: Replace element properties

### Contributing Guidelines

When contributing:
1. **No test files exist currently** - consider adding tests for new features
2. Follow semantic versioning
3. Ensure CI can build the code
4. Update documentation (README.md, code comments)
5. Code must not contain secrets
6. Clear commit messages following best practices

### Security Considerations

- Never commit API keys or secrets
- Use environment variables for sensitive configuration
- Report security issues privately to [email protected]
- All public members should be documented

### Common Development Tasks

1. **Adding a new tool**:
- Create new file in `src/tools/`
- Follow naming convention (under 35 chars, proper suffix)
- Implement using the standard pattern
- Register in `src/server.ts`
- Update README.md with tool description

2. **Modifying schemas**:
- Update relevant file in `src/schemas/`
- Ensure backward compatibility
- Update related tool implementations

3. **Debugging API issues**:
- Check request IDs in error responses
- Use MCP inspector for interactive debugging
- Verify environment variables are set correctly
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@kontent-ai/mcp-server",
"version": "0.14.0",
"version": "0.15.0",
"type": "module",
"scripts": {
"build": "rimraf build && tsc",
Expand Down
27 changes: 27 additions & 0 deletions src/schemas/filterVariantSchemas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ export const filterVariantsSchema = z.object({
.min(1)
.optional()
.describe("Array of references to users by their id or email"),
has_no_contributors: z
.boolean()
.optional()
.describe(
"Filter for content item language variants that have no contributors assigned",
),
completion_statuses: z
.array(z.enum(["unfinished", "completed", "not_translated", "all_done"]))
.min(1)
Expand Down Expand Up @@ -53,6 +59,27 @@ export const filterVariantsSchema = z.object({
.min(1)
.optional()
.describe("Array of workflows with workflow steps"),
taxonomy_groups: z
.array(
z.object({
taxonomy_identifier: referenceObjectSchema.describe(
"Reference to a taxonomy group by its id, codename, or external id",
),
term_identifiers: z
.array(referenceObjectSchema)
.describe(
"Array of references to taxonomy terms by their id, codename, or external id",
),
include_uncategorized: z
.boolean()
.describe(
"Whether to include content item language variants that don't have any taxonomy terms assigned in this taxonomy group",
),
}),
)
.min(1)
.optional()
.describe("Array of taxonomy groups with taxonomy terms to filter by"),

Choose a reason for hiding this comment

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

Simply "Array of taxonomy groups with taxonomy terms" should be enough to be consistent with the rest of descriptions.

order_by: z
.enum(["name", "due", "last_modified"])
.optional()
Expand Down
4 changes: 4 additions & 0 deletions src/tools/filter-variants-mapi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@ export const registerTool = (server: McpServer): void => {
search_phrase,
content_types,
contributors,
has_no_contributors,
completion_statuses,
language,
workflow_steps,
taxonomy_groups,
order_by,
order_direction,
continuation_token,
Expand All @@ -26,9 +28,11 @@ export const registerTool = (server: McpServer): void => {
search_phrase,
content_types,
contributors,
has_no_contributors,
completion_statuses,
language,
workflow_steps,
taxonomy_groups,
},
order: order_by
? {
Expand Down