# Phase 4 Plan 2: Create Linking Tools
## Objective
Create MCP tools for linking and querying entity relationships.
## Context
From ROADMAP.md Phase 4 requirements:
- Create `link_entities` tool
- Create `get_linked_entities` tool
Depends on 04-01 which adds schema and storage helpers.
## Tasks
### Task 1: Create linking tool functions
**File:** `src/tools/linking.ts`
Create tool implementations:
```typescript
import { z } from "zod";
import { linkEntities, unlinkEntities, getLinkedEntities } from "../storage/index.js";
export const linkEntitiesSchema = z.object({
sourceEntityId: z.string().describe("The entity to add the link to"),
targetEntityId: z.string().describe("The entity to link to"),
relationship: z.string().optional().describe("Relationship type (e.g., 'informs', 'validates', 'supports')"),
});
export const unlinkEntitiesSchema = z.object({
sourceEntityId: z.string().describe("The entity to remove the link from"),
targetEntityId: z.string().describe("The entity to unlink"),
});
export const getLinkedEntitiesSchema = z.object({
entityId: z.string().describe("The entity ID to get links for"),
});
export async function linkEntitiesTool(args: z.infer<typeof linkEntitiesSchema>) {
const success = await linkEntities(args.sourceEntityId, args.targetEntityId, args.relationship);
return { success, message: success ? "Entities linked" : "Failed to link entities" };
}
export async function unlinkEntitiesTool(args: z.infer<typeof unlinkEntitiesSchema>) {
const success = await unlinkEntities(args.sourceEntityId, args.targetEntityId);
return { success, message: success ? "Entities unlinked" : "Failed to unlink entities" };
}
export async function getLinkedEntitiesTool(args: z.infer<typeof getLinkedEntitiesSchema>) {
return await getLinkedEntities(args.entityId);
}
```
**Commit:** `feat(tools): add entity linking tool functions`
### Task 2: Export from tools index
**File:** `src/tools/index.ts`
Add exports:
```typescript
export {
linkEntitiesTool,
linkEntitiesSchema,
unlinkEntitiesTool,
unlinkEntitiesSchema,
getLinkedEntitiesTool,
getLinkedEntitiesSchema,
} from "./linking.js";
```
**Commit:** `feat(tools): export linking tools from index`
### Task 3: Register tools in MCP server
**File:** `src/index.ts`
Add tool registrations in a new ENTITY LINKING section:
```typescript
// ============================================================================
// ENTITY LINKING
// ============================================================================
server.tool(
"link_entities",
linkEntitiesSchema.shape,
{ title: "Link two entities together (e.g., persona to canvas)" },
async (args) => jsonResponse(await linkEntitiesTool(linkEntitiesSchema.parse(args)))
);
server.tool(
"unlink_entities",
unlinkEntitiesSchema.shape,
{ title: "Remove a link between two entities" },
async (args) => jsonResponse(await unlinkEntitiesTool(unlinkEntitiesSchema.parse(args)))
);
server.tool(
"get_linked_entities",
getLinkedEntitiesSchema.shape,
{ title: "Get all entities linked to a given entity" },
async (args) => jsonResponse(await getLinkedEntitiesTool(getLinkedEntitiesSchema.parse(args)))
);
```
**Commit:** `feat(mcp): register entity linking tools`
### Task 4: Add tool tests
**File:** `src/tools/linking.test.ts`
Test cases:
- link_entities creates valid link
- link_entities with relationship type
- unlink_entities removes link
- get_linked_entities returns resolved entities
- Tools handle invalid entity IDs
**Commit:** `test(tools): add linking tool tests`
## Verification
```bash
npm test -- src/tools/linking.test.ts
npm run build
```
## Dependencies
Requires 04-01 (schema and storage helpers).