Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
38 changes: 37 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ This SDK enables you to create custom MCP servers that Angie can discover and us
- [MCP Server Example](#mcp-server-example)
- [Adding Instructions to MCP Servers](#adding-instructions-to-mcp-servers)
- [Registering Tools](#registering-tools)
- [Tool Annotations](#tool-annotations)
- [Handling Tool Calls](#handling-tool-calls)
- [Best Practices](#best-practices)
- [Remote SSE and HTTP Streamable MCP servers](#remote-sse-and-http-streamable-mcp-servers)
Expand Down Expand Up @@ -105,7 +106,7 @@ The SDK covers three main abilities:

📖 **Documentation:**
- [MCP SDK Supported Features](./docs/angie-sdk-supported-features.md)
- [Tool Model Preferences](./docs/model-preferences.md) - Configure preferred AI models for your tools
- [Tool Annotations](./docs/tool-annotations.md) - Annotate tools with resource dependencies, model preferences, and more

---

Expand Down Expand Up @@ -317,6 +318,41 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({

---

## Tool Annotations

Angie extends MCP tool annotations with Angie-specific metadata. Import the annotation constants directly from `@elementor/angie-sdk`:

```typescript
import {
ANGIE_REQUIRED_RESOURCES,
ANGIE_MODEL_PREFERENCES,
ANGIE_EXTENDED_TIMEOUT,
MCP_READONLY,
ToolAnnotations,
} from '@elementor/angie-sdk';

server.tool(
'analyze-page-layout',
'Analyzes the current page layout and returns suggestions',
{ /* input schema */ },
{
[MCP_READONLY]: true,
[ANGIE_EXTENDED_TIMEOUT]: { timeoutMs: 30000 },
[ANGIE_REQUIRED_RESOURCES]: [
{ uri: 'elementor://page/layout', whenToUse: 'Always — needed to read the page structure' }
],
[ANGIE_MODEL_PREFERENCES]: {
hints: [{ name: 'claude-sonnet' }]
}
} as ToolAnnotations,
async (args) => { /* handler */ }
);
```

📖 See [Tool Annotations](./docs/tool-annotations.md) for full reference.

---

## Handling Tool Calls

Implement a handler for `CallToolRequestSchema`:
Expand Down
10 changes: 6 additions & 4 deletions docs/angie-sdk-supported-features.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,17 @@ These annotations are **Angie-specific** and extend standard MCP tool annotation
Declare which resources a tool needs before execution. Angie will fetch these resources automatically before calling the tool.

```typescript
import { ANGIE_REQUIRED_RESOURCES, ToolAnnotations } from '@elementor/angie-sdk';

server.tool('update-element', 'Update an Elementor element', {
elementId: z.string(),
changes: z.object({ /* ... */ }),
}, {
'angie/requiredResources': [
{ uri: 'elementor://page-context', description: 'Current page structure' },
{ uri: 'elementor://selected-element', description: 'Currently selected element' }
[ANGIE_REQUIRED_RESOURCES]: [
{ uri: 'elementor://page-context', whenToUse: 'Current page structure' },
{ uri: 'elementor://selected-element', whenToUse: 'Currently selected element' }
]
}, handler);
} as ToolAnnotations, handler);
```

**How it works:**
Expand Down
66 changes: 0 additions & 66 deletions docs/model-preferences.md

This file was deleted.

183 changes: 183 additions & 0 deletions docs/tool-annotations.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
# Angie Tool Annotations

Angie exposes a set of annotation constants and interfaces that MCP tool authors can use to attach Angie-specific metadata to their tools. These are exported directly from `@elementor/angie-sdk`.

## Available Annotations

| Constant | Value | Purpose |
|---|---|---|
| `ANGIE_REQUIRED_RESOURCES` | `'angie/requiredResources'` | Declare resources the tool needs |
| `ANGIE_MODEL_PREFERENCES` | `'angie/modelPreferences'` | Request a specific AI model |
| `ANGIE_EXTENDED_TIMEOUT` | `'angie/extendedTimeout'` | Request a longer execution timeout |
| `MCP_READONLY` | `'readOnlyHint'` | Mark a tool as read-only |

---

## `ANGIE_REQUIRED_RESOURCES`

Declare which resources the tool expects Angie to fetch and provide before execution.

```typescript
interface AngieRequiredResource {
uri: string; // Resource URI to fetch
whenToUse: string; // Human-readable description of when this resource is needed
params?: Record<string, string>; // Optional URI template parameters
}
```

**Example:**

```typescript
import { ANGIE_REQUIRED_RESOURCES, ToolAnnotations } from '@elementor/angie-sdk';

server.tool(
'update-page-styles',
'Updates the CSS styles for the current page',
{ /* input schema */ },
{
[ANGIE_REQUIRED_RESOURCES]: [
{
uri: 'elementor://page/styles',
whenToUse: 'Always — needed to read current page styles before updating',
}
]
} as ToolAnnotations,
async (args) => { /* handler */ }
);
```

---

## `ANGIE_MODEL_PREFERENCES`

Request a specific AI model for planning and execution of this tool. When the tool is selected, Angie uses this preference to override the default model.

```typescript
interface AngieModelPreferences {
hints?: Array<{ name: string }>; // Ordered list of preferred model names
costPriority?: number; // 0–1 (future use)
speedPriority?: number; // 0–1 (future use)
intelligencePriority?: number; // 0–1 (future use)
}
```

### Model Selection Priority

Angie resolves the model in this order:

1. **User preference (internal users only)** — `executionModel` if provided and different from the system default
2. **Tool annotation** — `angie/modelPreferences.hints[0]` if user preference is default or absent
3. **System default** — falls back if neither is available

**Example:**

```typescript
import { ANGIE_MODEL_PREFERENCES, ToolAnnotations } from '@elementor/angie-sdk';

server.tool(
'generate-custom-css',
'Generates CSS code based on design requirements',
{ /* input schema */ },
{
[ANGIE_MODEL_PREFERENCES]: {
hints: [
{ name: 'claude-sonnet' }, // First choice
{ name: 'gpt-4.1' } // Fallback
],
intelligencePriority: 0.9 // Optional: for future use
}
} as ToolAnnotations,
async (args) => { /* handler */ }
);
```

> Based on the [MCP Sampling specification](https://modelcontextprotocol.io/specification/2025-06-18/client/sampling). First hint is the most preferred; subsequent hints are fallbacks.

---

## `ANGIE_EXTENDED_TIMEOUT`

Request a longer execution timeout for tools that perform heavy or slow operations (e.g., large DOM mutations, external API calls).

```typescript
interface AngieExtendedTimeout {
timeoutMs: number; // Timeout in milliseconds
}
```

**Example:**

```typescript
import { ANGIE_EXTENDED_TIMEOUT, ToolAnnotations } from '@elementor/angie-sdk';

server.tool(
'bulk-update-elements',
'Updates all elements on the page in one operation',
{ /* input schema */ },
{
[ANGIE_EXTENDED_TIMEOUT]: {
timeoutMs: 60000 // 60 seconds
}
} as ToolAnnotations,
async (args) => { /* handler */ }
);
```

---

## `MCP_READONLY`

Mark a tool as read-only. Angie uses this hint to understand that the tool does not mutate any state, which can affect planning and user confirmation flows.

**Example:**

```typescript
import { MCP_READONLY, ToolAnnotations } from '@elementor/angie-sdk';

server.tool(
'get-page-structure',
'Returns the structure of the current page',
{ /* input schema */ },
{
[MCP_READONLY]: true
} as ToolAnnotations,
async (args) => { /* handler */ }
);
```

---

## Using Multiple Annotations Together

All annotations can be combined on a single tool:

```typescript
import {
ANGIE_REQUIRED_RESOURCES,
ANGIE_MODEL_PREFERENCES,
ANGIE_EXTENDED_TIMEOUT,
MCP_READONLY,
ToolAnnotations,
} from '@elementor/angie-sdk';

server.tool(
'analyze-page-layout',
'Analyzes the current page layout and returns suggestions',
{ /* input schema */ },
{
[MCP_READONLY]: true,
[ANGIE_EXTENDED_TIMEOUT]: { timeoutMs: 30000 },
[ANGIE_REQUIRED_RESOURCES]: [
{
uri: 'elementor://page/layout',
whenToUse: 'Always — needed to read the page structure',
}
],
[ANGIE_MODEL_PREFERENCES]: {
hints: [{ name: 'claude-sonnet' }],
intelligencePriority: 0.9
}
} as ToolAnnotations,
async (args) => { /* handler */ }
);
```
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@elementor/angie-sdk",
"version": "1.4.1",
"version": "1.4.2",
"description": "TypeScript SDK for Angie AI assistant",
"main": "dist/index.cjs",
"module": "dist/index.js",
Expand Down
25 changes: 25 additions & 0 deletions src/angie-annotations.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { describe, expect, it } from '@jest/globals';
import {
ANGIE_REQUIRED_RESOURCES,
ANGIE_MODEL_PREFERENCES,
ANGIE_EXTENDED_TIMEOUT,
MCP_READONLY,
} from './angie-annotations';

describe('angie-annotations', () => {
it('ANGIE_REQUIRED_RESOURCES has the correct value', () => {
expect(ANGIE_REQUIRED_RESOURCES).toBe('angie/requiredResources');
});

it('ANGIE_MODEL_PREFERENCES has the correct value', () => {
expect(ANGIE_MODEL_PREFERENCES).toBe('angie/modelPreferences');
});

it('ANGIE_EXTENDED_TIMEOUT has the correct value', () => {
expect(ANGIE_EXTENDED_TIMEOUT).toBe('angie/extendedTimeout');
});

it('MCP_READONLY has the correct value', () => {
expect(MCP_READONLY).toBe('readOnlyHint');
});
});
Loading