circuito-mcp 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client.d.ts +71 -0
- package/dist/client.js +92 -0
- package/dist/client.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +131 -0
- package/dist/index.js.map +1 -0
- package/dist/tools.d.ts +3 -0
- package/dist/tools.js +105 -0
- package/dist/tools.js.map +1 -0
- package/package.json +25 -0
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
export interface InovarClientConfig {
|
|
2
|
+
apiUrl: string;
|
|
3
|
+
apiToken: string;
|
|
4
|
+
}
|
|
5
|
+
export declare class InovarClient {
|
|
6
|
+
private baseUrl;
|
|
7
|
+
private token;
|
|
8
|
+
constructor(config: InovarClientConfig);
|
|
9
|
+
private request;
|
|
10
|
+
listBoards(): Promise<{
|
|
11
|
+
boards: Array<{
|
|
12
|
+
id: string;
|
|
13
|
+
name: string;
|
|
14
|
+
prefix: string | null;
|
|
15
|
+
aiSpecEnabled: boolean;
|
|
16
|
+
}>;
|
|
17
|
+
}>;
|
|
18
|
+
listCards(boardId: string, search?: string): Promise<{
|
|
19
|
+
cards: Array<{
|
|
20
|
+
id: string;
|
|
21
|
+
number: number;
|
|
22
|
+
title: string;
|
|
23
|
+
}>;
|
|
24
|
+
}>;
|
|
25
|
+
searchCards(boardId: string, query: string): Promise<{
|
|
26
|
+
cards: Array<{
|
|
27
|
+
id: string;
|
|
28
|
+
number: number;
|
|
29
|
+
title: string;
|
|
30
|
+
}>;
|
|
31
|
+
}>;
|
|
32
|
+
getCard(cardId: string): Promise<{
|
|
33
|
+
card: Record<string, unknown>;
|
|
34
|
+
}>;
|
|
35
|
+
/**
|
|
36
|
+
* Resolve a card reference to a UUID.
|
|
37
|
+
* Accepts: UUID, or card code like "CALC-1" (prefix-number).
|
|
38
|
+
*/
|
|
39
|
+
resolveCardId(ref: string): Promise<string>;
|
|
40
|
+
updateCardSpec(cardId: string, spec: string): Promise<{
|
|
41
|
+
card: Record<string, unknown>;
|
|
42
|
+
}>;
|
|
43
|
+
listCardTypes(): Promise<{
|
|
44
|
+
cardTypes: Array<{
|
|
45
|
+
id: string;
|
|
46
|
+
name: string;
|
|
47
|
+
}>;
|
|
48
|
+
}>;
|
|
49
|
+
getBoard(boardId: string): Promise<{
|
|
50
|
+
board: {
|
|
51
|
+
id: string;
|
|
52
|
+
name: string;
|
|
53
|
+
columns: Array<{
|
|
54
|
+
id: string;
|
|
55
|
+
name: string;
|
|
56
|
+
order: number;
|
|
57
|
+
}>;
|
|
58
|
+
};
|
|
59
|
+
}>;
|
|
60
|
+
moveCard(cardId: string, columnId: string): Promise<{
|
|
61
|
+
card: Record<string, unknown>;
|
|
62
|
+
}>;
|
|
63
|
+
createCard(boardId: string, input: {
|
|
64
|
+
title: string;
|
|
65
|
+
description?: string;
|
|
66
|
+
cardTypeId: string;
|
|
67
|
+
columnId?: string;
|
|
68
|
+
}): Promise<{
|
|
69
|
+
card: Record<string, unknown>;
|
|
70
|
+
}>;
|
|
71
|
+
}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
export class InovarClient {
|
|
2
|
+
baseUrl;
|
|
3
|
+
token;
|
|
4
|
+
constructor(config) {
|
|
5
|
+
this.baseUrl = config.apiUrl.replace(/\/$/, '');
|
|
6
|
+
this.token = config.apiToken;
|
|
7
|
+
}
|
|
8
|
+
async request(path, options = {}) {
|
|
9
|
+
const res = await fetch(`${this.baseUrl}${path}`, {
|
|
10
|
+
...options,
|
|
11
|
+
headers: {
|
|
12
|
+
'Content-Type': 'application/json',
|
|
13
|
+
Authorization: `Bearer ${this.token}`,
|
|
14
|
+
...options.headers,
|
|
15
|
+
},
|
|
16
|
+
});
|
|
17
|
+
if (!res.ok) {
|
|
18
|
+
const text = await res.text();
|
|
19
|
+
throw new Error(`Inovar API error ${res.status}: ${text}`);
|
|
20
|
+
}
|
|
21
|
+
return res.json();
|
|
22
|
+
}
|
|
23
|
+
async listBoards() {
|
|
24
|
+
return this.request('/boards');
|
|
25
|
+
}
|
|
26
|
+
async listCards(boardId, search) {
|
|
27
|
+
const params = new URLSearchParams();
|
|
28
|
+
if (search)
|
|
29
|
+
params.set('q', search);
|
|
30
|
+
const qs = params.toString();
|
|
31
|
+
return this.request(`/boards/${boardId}/cards${qs ? `?${qs}` : ''}`);
|
|
32
|
+
}
|
|
33
|
+
async searchCards(boardId, query) {
|
|
34
|
+
return this.request(`/boards/${boardId}/cards/search?q=${encodeURIComponent(query)}`);
|
|
35
|
+
}
|
|
36
|
+
async getCard(cardId) {
|
|
37
|
+
return this.request(`/cards/${cardId}`);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Resolve a card reference to a UUID.
|
|
41
|
+
* Accepts: UUID, or card code like "CALC-1" (prefix-number).
|
|
42
|
+
*/
|
|
43
|
+
async resolveCardId(ref) {
|
|
44
|
+
const uuidPattern = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
45
|
+
if (uuidPattern.test(ref))
|
|
46
|
+
return ref;
|
|
47
|
+
// Parse "PREFIX-NUMBER" format
|
|
48
|
+
const match = ref.match(/^(.+)-(\d+)$/);
|
|
49
|
+
if (!match)
|
|
50
|
+
throw new Error(`Invalid card reference "${ref}". Use a UUID or card code like "CALC-1".`);
|
|
51
|
+
const [, prefix, numberStr] = match;
|
|
52
|
+
const number = parseInt(numberStr, 10);
|
|
53
|
+
// Find the board by prefix
|
|
54
|
+
const { boards } = await this.listBoards();
|
|
55
|
+
const board = boards.find((b) => b.prefix?.toLowerCase() === prefix.toLowerCase());
|
|
56
|
+
if (!board) {
|
|
57
|
+
const available = boards.filter((b) => b.prefix).map((b) => b.prefix).join(', ');
|
|
58
|
+
throw new Error(`Board with prefix "${prefix}" not found. Available prefixes: ${available}`);
|
|
59
|
+
}
|
|
60
|
+
// Find the card by number in that board
|
|
61
|
+
const { cards } = await this.listCards(board.id);
|
|
62
|
+
const card = cards.find((c) => c.number === number);
|
|
63
|
+
if (!card)
|
|
64
|
+
throw new Error(`Card ${ref} not found in board "${board.name}".`);
|
|
65
|
+
return card.id;
|
|
66
|
+
}
|
|
67
|
+
async updateCardSpec(cardId, spec) {
|
|
68
|
+
return this.request(`/cards/${cardId}`, {
|
|
69
|
+
method: 'PATCH',
|
|
70
|
+
body: JSON.stringify({ spec }),
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
async listCardTypes() {
|
|
74
|
+
return this.request('/card-types');
|
|
75
|
+
}
|
|
76
|
+
async getBoard(boardId) {
|
|
77
|
+
return this.request(`/boards/${boardId}`);
|
|
78
|
+
}
|
|
79
|
+
async moveCard(cardId, columnId) {
|
|
80
|
+
return this.request(`/cards/${cardId}/move`, {
|
|
81
|
+
method: 'POST',
|
|
82
|
+
body: JSON.stringify({ columnId }),
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
async createCard(boardId, input) {
|
|
86
|
+
return this.request(`/boards/${boardId}/cards`, {
|
|
87
|
+
method: 'POST',
|
|
88
|
+
body: JSON.stringify(input),
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
3
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
import { InovarClient } from './client.js';
|
|
6
|
+
const apiUrl = process.env.INOVAR_API_URL;
|
|
7
|
+
const apiToken = process.env.INOVAR_API_TOKEN;
|
|
8
|
+
if (!apiUrl || !apiToken) {
|
|
9
|
+
console.error('Missing INOVAR_API_URL or INOVAR_API_TOKEN environment variables');
|
|
10
|
+
process.exit(1);
|
|
11
|
+
}
|
|
12
|
+
const client = new InovarClient({ apiUrl, apiToken });
|
|
13
|
+
const server = new McpServer({
|
|
14
|
+
name: 'inovar-kanban',
|
|
15
|
+
version: '0.1.0',
|
|
16
|
+
});
|
|
17
|
+
server.tool('list_boards', 'List all boards with their columns and available card types', {}, async () => {
|
|
18
|
+
const [boardsData, typesData] = await Promise.all([
|
|
19
|
+
client.listBoards(),
|
|
20
|
+
client.listCardTypes(),
|
|
21
|
+
]);
|
|
22
|
+
// Enrich each board with its columns
|
|
23
|
+
const enriched = await Promise.all(boardsData.boards.map(async (b) => {
|
|
24
|
+
const { board } = await client.getBoard(b.id);
|
|
25
|
+
return {
|
|
26
|
+
...b,
|
|
27
|
+
columns: board.columns.sort((a, b) => a.order - b.order).map((c) => ({ name: c.name, id: c.id })),
|
|
28
|
+
};
|
|
29
|
+
}));
|
|
30
|
+
const result = {
|
|
31
|
+
boards: enriched,
|
|
32
|
+
cardTypes: typesData.cardTypes,
|
|
33
|
+
};
|
|
34
|
+
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
35
|
+
});
|
|
36
|
+
server.tool('list_cards', 'List cards from a specific board', { boardId: z.string().describe('The board ID'), search: z.string().optional().describe('Search by card title') }, async ({ boardId, search }) => {
|
|
37
|
+
const data = await client.listCards(boardId, search);
|
|
38
|
+
return { content: [{ type: 'text', text: JSON.stringify(data.cards, null, 2) }] };
|
|
39
|
+
});
|
|
40
|
+
server.tool('list_columns', 'List all columns of a board with their IDs and names, ordered by position', { boardId: z.string().describe('The board ID') }, async ({ boardId }) => {
|
|
41
|
+
const { board } = await client.getBoard(boardId);
|
|
42
|
+
const columns = board.columns.sort((a, b) => a.order - b.order).map((c) => ({ id: c.id, name: c.name }));
|
|
43
|
+
return { content: [{ type: 'text', text: JSON.stringify(columns, null, 2) }] };
|
|
44
|
+
});
|
|
45
|
+
server.tool('move_card', 'Move a card to a different column. Accepts card code (e.g. "CALC-1") and column name.', {
|
|
46
|
+
cardRef: z.string().describe('Card UUID or code (e.g. "CALC-1", "AUTO-42")'),
|
|
47
|
+
columnName: z.string().describe('Target column name (e.g. "Doing", "Done")'),
|
|
48
|
+
}, async ({ cardRef, columnName }) => {
|
|
49
|
+
const cardId = await client.resolveCardId(cardRef);
|
|
50
|
+
// Get the card to find its board
|
|
51
|
+
const { card } = await client.getCard(cardId);
|
|
52
|
+
const boardId = card.boardId;
|
|
53
|
+
const { board } = await client.getBoard(boardId);
|
|
54
|
+
const column = board.columns.find((c) => c.name.toLowerCase() === columnName.toLowerCase());
|
|
55
|
+
if (!column) {
|
|
56
|
+
const available = board.columns.sort((a, b) => a.order - b.order).map((c) => c.name).join(', ');
|
|
57
|
+
return { content: [{ type: 'text', text: `Error: column "${columnName}" not found. Available: ${available}` }] };
|
|
58
|
+
}
|
|
59
|
+
await client.moveCard(cardId, column.id);
|
|
60
|
+
return { content: [{ type: 'text', text: `Card ${cardRef} moved to "${column.name}"` }] };
|
|
61
|
+
});
|
|
62
|
+
server.tool('get_card', 'Get full details of a card including description and spec. Accepts UUID or card code (e.g. "CALC-1").', { cardRef: z.string().describe('Card UUID or code (e.g. "CALC-1", "AUTO-42")') }, async ({ cardRef }) => {
|
|
63
|
+
const cardId = await client.resolveCardId(cardRef);
|
|
64
|
+
const data = await client.getCard(cardId);
|
|
65
|
+
return { content: [{ type: 'text', text: JSON.stringify(data.card, null, 2) }] };
|
|
66
|
+
});
|
|
67
|
+
server.tool('update_card_spec', 'Write or update the spec markdown on a card. Accepts UUID or card code (e.g. "CALC-1").', {
|
|
68
|
+
cardRef: z.string().describe('Card UUID or code (e.g. "CALC-1", "AUTO-42")'),
|
|
69
|
+
spec: z.string().describe('The spec content in markdown format'),
|
|
70
|
+
}, async ({ cardRef, spec }) => {
|
|
71
|
+
const cardId = await client.resolveCardId(cardRef);
|
|
72
|
+
await client.updateCardSpec(cardId, spec);
|
|
73
|
+
return { content: [{ type: 'text', text: `Spec updated successfully on card ${cardRef}` }] };
|
|
74
|
+
});
|
|
75
|
+
server.tool('create_card', 'Create a new card on a board. Card type and column are auto-resolved if not provided.', {
|
|
76
|
+
boardId: z.string().describe('The board ID'),
|
|
77
|
+
title: z.string().describe('Card title'),
|
|
78
|
+
description: z.string().optional().describe('Card description (optional, supports markdown)'),
|
|
79
|
+
cardTypeName: z.string().optional().describe('Card type name (e.g. "Story", "Bug", "Task"). Auto-resolves to first available if omitted.'),
|
|
80
|
+
columnName: z.string().optional().describe('Column name to place the card in (e.g. "Backlog"). Auto-resolves to first column if omitted.'),
|
|
81
|
+
}, async ({ boardId, title, description, cardTypeName, columnName }) => {
|
|
82
|
+
// Fetch all context needed in parallel
|
|
83
|
+
const [{ cardTypes }, { board }] = await Promise.all([
|
|
84
|
+
client.listCardTypes(),
|
|
85
|
+
client.getBoard(boardId),
|
|
86
|
+
]);
|
|
87
|
+
if (cardTypes.length === 0) {
|
|
88
|
+
return { content: [{ type: 'text', text: 'Error: no card types found. Create at least one card type first.' }] };
|
|
89
|
+
}
|
|
90
|
+
if (board.columns.length === 0) {
|
|
91
|
+
return { content: [{ type: 'text', text: 'Error: board has no columns.' }] };
|
|
92
|
+
}
|
|
93
|
+
// Resolve card type by name or default to first
|
|
94
|
+
let cardTypeId;
|
|
95
|
+
if (cardTypeName) {
|
|
96
|
+
const match = cardTypes.find((ct) => ct.name.toLowerCase() === cardTypeName.toLowerCase());
|
|
97
|
+
if (!match) {
|
|
98
|
+
const available = cardTypes.map((ct) => ct.name).join(', ');
|
|
99
|
+
return { content: [{ type: 'text', text: `Error: card type "${cardTypeName}" not found. Available: ${available}` }] };
|
|
100
|
+
}
|
|
101
|
+
cardTypeId = match.id;
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
cardTypeId = cardTypes[0].id;
|
|
105
|
+
}
|
|
106
|
+
// Resolve column by name or default to first
|
|
107
|
+
const sortedColumns = [...board.columns].sort((a, b) => a.order - b.order);
|
|
108
|
+
let columnId;
|
|
109
|
+
if (columnName) {
|
|
110
|
+
const match = sortedColumns.find((c) => c.name.toLowerCase() === columnName.toLowerCase());
|
|
111
|
+
if (!match) {
|
|
112
|
+
const available = sortedColumns.map((c) => c.name).join(', ');
|
|
113
|
+
return { content: [{ type: 'text', text: `Error: column "${columnName}" not found. Available: ${available}` }] };
|
|
114
|
+
}
|
|
115
|
+
columnId = match.id;
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
columnId = sortedColumns[0].id;
|
|
119
|
+
}
|
|
120
|
+
const data = await client.createCard(boardId, { title, description, cardTypeId, columnId });
|
|
121
|
+
return { content: [{ type: 'text', text: JSON.stringify(data.card, null, 2) }] };
|
|
122
|
+
});
|
|
123
|
+
async function main() {
|
|
124
|
+
const transport = new StdioServerTransport();
|
|
125
|
+
await server.connect(transport);
|
|
126
|
+
}
|
|
127
|
+
main().catch((err) => {
|
|
128
|
+
console.error('Fatal error:', err);
|
|
129
|
+
process.exit(1);
|
|
130
|
+
});
|
|
131
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/tools.d.ts
ADDED
package/dist/tools.js
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export function registerTools(server, client) {
|
|
3
|
+
server.tool('list_boards', 'List all boards with their columns and available card types', {}, async () => {
|
|
4
|
+
const [boardsData, typesData] = await Promise.all([
|
|
5
|
+
client.listBoards(),
|
|
6
|
+
client.listCardTypes(),
|
|
7
|
+
]);
|
|
8
|
+
const enriched = await Promise.all(boardsData.boards.map(async (b) => {
|
|
9
|
+
const { board } = await client.getBoard(b.id);
|
|
10
|
+
return {
|
|
11
|
+
...b,
|
|
12
|
+
columns: board.columns.sort((a, b) => a.order - b.order).map((c) => ({ name: c.name, id: c.id })),
|
|
13
|
+
};
|
|
14
|
+
}));
|
|
15
|
+
const result = {
|
|
16
|
+
boards: enriched,
|
|
17
|
+
cardTypes: typesData.cardTypes,
|
|
18
|
+
};
|
|
19
|
+
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
20
|
+
});
|
|
21
|
+
server.tool('list_cards', 'List cards from a specific board', { boardId: z.string().describe('The board ID'), search: z.string().optional().describe('Search by card title') }, async ({ boardId, search }) => {
|
|
22
|
+
const data = await client.listCards(boardId, search);
|
|
23
|
+
return { content: [{ type: 'text', text: JSON.stringify(data.cards, null, 2) }] };
|
|
24
|
+
});
|
|
25
|
+
server.tool('list_columns', 'List all columns of a board with their IDs and names, ordered by position', { boardId: z.string().describe('The board ID') }, async ({ boardId }) => {
|
|
26
|
+
const { board } = await client.getBoard(boardId);
|
|
27
|
+
const columns = board.columns.sort((a, b) => a.order - b.order).map((c) => ({ id: c.id, name: c.name }));
|
|
28
|
+
return { content: [{ type: 'text', text: JSON.stringify(columns, null, 2) }] };
|
|
29
|
+
});
|
|
30
|
+
server.tool('move_card', 'Move a card to a different column. Accepts card code (e.g. "CALC-1") and column name.', {
|
|
31
|
+
cardRef: z.string().describe('Card UUID or code (e.g. "CALC-1", "AUTO-42")'),
|
|
32
|
+
columnName: z.string().describe('Target column name (e.g. "Doing", "Done")'),
|
|
33
|
+
}, async ({ cardRef, columnName }) => {
|
|
34
|
+
const cardId = await client.resolveCardId(cardRef);
|
|
35
|
+
const { card } = await client.getCard(cardId);
|
|
36
|
+
const boardId = card.boardId;
|
|
37
|
+
const { board } = await client.getBoard(boardId);
|
|
38
|
+
const column = board.columns.find((c) => c.name.toLowerCase() === columnName.toLowerCase());
|
|
39
|
+
if (!column) {
|
|
40
|
+
const available = board.columns.sort((a, b) => a.order - b.order).map((c) => c.name).join(', ');
|
|
41
|
+
return { content: [{ type: 'text', text: `Error: column "${columnName}" not found. Available: ${available}` }] };
|
|
42
|
+
}
|
|
43
|
+
await client.moveCard(cardId, column.id);
|
|
44
|
+
return { content: [{ type: 'text', text: `Card ${cardRef} moved to "${column.name}"` }] };
|
|
45
|
+
});
|
|
46
|
+
server.tool('get_card', 'Get full details of a card including description and spec. Accepts UUID or card code (e.g. "CALC-1").', { cardRef: z.string().describe('Card UUID or code (e.g. "CALC-1", "AUTO-42")') }, async ({ cardRef }) => {
|
|
47
|
+
const cardId = await client.resolveCardId(cardRef);
|
|
48
|
+
const data = await client.getCard(cardId);
|
|
49
|
+
return { content: [{ type: 'text', text: JSON.stringify(data.card, null, 2) }] };
|
|
50
|
+
});
|
|
51
|
+
server.tool('update_card_spec', 'Write or update the spec markdown on a card. Accepts UUID or card code (e.g. "CALC-1").', {
|
|
52
|
+
cardRef: z.string().describe('Card UUID or code (e.g. "CALC-1", "AUTO-42")'),
|
|
53
|
+
spec: z.string().describe('The spec content in markdown format'),
|
|
54
|
+
}, async ({ cardRef, spec }) => {
|
|
55
|
+
const cardId = await client.resolveCardId(cardRef);
|
|
56
|
+
await client.updateCardSpec(cardId, spec);
|
|
57
|
+
return { content: [{ type: 'text', text: `Spec updated successfully on card ${cardRef}` }] };
|
|
58
|
+
});
|
|
59
|
+
server.tool('create_card', 'Create a new card on a board. Card type and column are auto-resolved if not provided.', {
|
|
60
|
+
boardId: z.string().describe('The board ID'),
|
|
61
|
+
title: z.string().describe('Card title'),
|
|
62
|
+
description: z.string().optional().describe('Card description (optional, supports markdown)'),
|
|
63
|
+
cardTypeName: z.string().optional().describe('Card type name (e.g. "Story", "Bug", "Task"). Auto-resolves to first available if omitted.'),
|
|
64
|
+
columnName: z.string().optional().describe('Column name to place the card in (e.g. "Backlog"). Auto-resolves to first column if omitted.'),
|
|
65
|
+
}, async ({ boardId, title, description, cardTypeName, columnName }) => {
|
|
66
|
+
const [{ cardTypes }, { board }] = await Promise.all([
|
|
67
|
+
client.listCardTypes(),
|
|
68
|
+
client.getBoard(boardId),
|
|
69
|
+
]);
|
|
70
|
+
if (cardTypes.length === 0) {
|
|
71
|
+
return { content: [{ type: 'text', text: 'Error: no card types found. Create at least one card type first.' }] };
|
|
72
|
+
}
|
|
73
|
+
if (board.columns.length === 0) {
|
|
74
|
+
return { content: [{ type: 'text', text: 'Error: board has no columns.' }] };
|
|
75
|
+
}
|
|
76
|
+
let cardTypeId;
|
|
77
|
+
if (cardTypeName) {
|
|
78
|
+
const match = cardTypes.find((ct) => ct.name.toLowerCase() === cardTypeName.toLowerCase());
|
|
79
|
+
if (!match) {
|
|
80
|
+
const available = cardTypes.map((ct) => ct.name).join(', ');
|
|
81
|
+
return { content: [{ type: 'text', text: `Error: card type "${cardTypeName}" not found. Available: ${available}` }] };
|
|
82
|
+
}
|
|
83
|
+
cardTypeId = match.id;
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
cardTypeId = cardTypes[0].id;
|
|
87
|
+
}
|
|
88
|
+
const sortedColumns = [...board.columns].sort((a, b) => a.order - b.order);
|
|
89
|
+
let columnId;
|
|
90
|
+
if (columnName) {
|
|
91
|
+
const match = sortedColumns.find((c) => c.name.toLowerCase() === columnName.toLowerCase());
|
|
92
|
+
if (!match) {
|
|
93
|
+
const available = sortedColumns.map((c) => c.name).join(', ');
|
|
94
|
+
return { content: [{ type: 'text', text: `Error: column "${columnName}" not found. Available: ${available}` }] };
|
|
95
|
+
}
|
|
96
|
+
columnId = match.id;
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
columnId = sortedColumns[0].id;
|
|
100
|
+
}
|
|
101
|
+
const data = await client.createCard(boardId, { title, description, cardTypeId, columnId });
|
|
102
|
+
return { content: [{ type: 'text', text: JSON.stringify(data.card, null, 2) }] };
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "circuito-mcp",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"description": "MCP server for Inovar Kanban - manage boards, cards and specs via Model Context Protocol",
|
|
7
|
+
"bin": {
|
|
8
|
+
"circuito-mcp": "dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist"
|
|
12
|
+
],
|
|
13
|
+
"scripts": {
|
|
14
|
+
"build": "tsc",
|
|
15
|
+
"dev": "tsc --watch"
|
|
16
|
+
},
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"@modelcontextprotocol/sdk": "^1.12.0",
|
|
19
|
+
"zod": "^3.25.28"
|
|
20
|
+
},
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"@types/node": "^22.0.0",
|
|
23
|
+
"typescript": "^5.9.3"
|
|
24
|
+
}
|
|
25
|
+
}
|