seizn-mcp 1.0.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/LICENSE +90 -0
- package/NOTICE +10 -0
- package/README.md +139 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +416 -0
- package/package.json +58 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
Apache License
|
|
2
|
+
Version 2.0, January 2004
|
|
3
|
+
http://www.apache.org/licenses/
|
|
4
|
+
|
|
5
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
6
|
+
|
|
7
|
+
1. Definitions.
|
|
8
|
+
|
|
9
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
10
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
11
|
+
|
|
12
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
13
|
+
the copyright owner that is granting the License.
|
|
14
|
+
|
|
15
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
16
|
+
other entities that control, are controlled by, or are under common
|
|
17
|
+
control with that entity.
|
|
18
|
+
|
|
19
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
20
|
+
exercising permissions granted by this License.
|
|
21
|
+
|
|
22
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
23
|
+
including but not limited to software source code, documentation
|
|
24
|
+
source, and configuration files.
|
|
25
|
+
|
|
26
|
+
"Object" form shall mean any form resulting from mechanical
|
|
27
|
+
transformation or translation of a Source form, including but
|
|
28
|
+
not limited to compiled object code, generated documentation,
|
|
29
|
+
and conversions to other media types.
|
|
30
|
+
|
|
31
|
+
"Work" shall mean the work of authorship, whether in Source or
|
|
32
|
+
Object form, made available under the License.
|
|
33
|
+
|
|
34
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
35
|
+
form, that is based on (or derived from) the Work.
|
|
36
|
+
|
|
37
|
+
"Contribution" shall mean any work of authorship submitted to the
|
|
38
|
+
Licensor for inclusion in the Work.
|
|
39
|
+
|
|
40
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
41
|
+
on behalf of whom a Contribution has been received by Licensor.
|
|
42
|
+
|
|
43
|
+
2. Grant of Copyright License. Each Contributor hereby grants to You a
|
|
44
|
+
perpetual, worldwide, non-exclusive, no-charge, royalty-free,
|
|
45
|
+
irrevocable copyright license to reproduce, prepare Derivative Works of,
|
|
46
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
47
|
+
Work and such Derivative Works in Source or Object form.
|
|
48
|
+
|
|
49
|
+
3. Grant of Patent License. Each Contributor hereby grants to You a
|
|
50
|
+
perpetual, worldwide, non-exclusive, no-charge, royalty-free,
|
|
51
|
+
irrevocable patent license to make, have made, use, offer to sell,
|
|
52
|
+
sell, import, and otherwise transfer the Work.
|
|
53
|
+
|
|
54
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
55
|
+
Work or Derivative Works thereof in any medium, provided that You:
|
|
56
|
+
(a) give recipients a copy of this License; and
|
|
57
|
+
(b) cause modified files to carry prominent notices; and
|
|
58
|
+
(c) retain all copyright, patent, trademark, and attribution notices; and
|
|
59
|
+
(d) include the NOTICE file contents in Derivative Works.
|
|
60
|
+
|
|
61
|
+
5. Submission of Contributions. Any Contribution submitted for inclusion
|
|
62
|
+
in the Work shall be under this License.
|
|
63
|
+
|
|
64
|
+
6. Trademarks. This License does not grant permission to use trade names,
|
|
65
|
+
trademarks, service marks, or product names of the Licensor.
|
|
66
|
+
|
|
67
|
+
7. Disclaimer of Warranty. THE WORK IS PROVIDED "AS IS", WITHOUT WARRANTIES
|
|
68
|
+
OF ANY KIND.
|
|
69
|
+
|
|
70
|
+
8. Limitation of Liability. IN NO EVENT SHALL ANY CONTRIBUTOR BE LIABLE
|
|
71
|
+
FOR ANY DAMAGES.
|
|
72
|
+
|
|
73
|
+
9. Accepting Warranty or Additional Liability. You may offer support,
|
|
74
|
+
warranty, or indemnity for a fee.
|
|
75
|
+
|
|
76
|
+
END OF TERMS AND CONDITIONS
|
|
77
|
+
|
|
78
|
+
Copyright 2024-2026 Seizn (https://seizn.com)
|
|
79
|
+
|
|
80
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
81
|
+
you may not use this file except in compliance with the License.
|
|
82
|
+
You may obtain a copy of the License at
|
|
83
|
+
|
|
84
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
85
|
+
|
|
86
|
+
Unless required by applicable law or agreed to in writing, software
|
|
87
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
88
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
89
|
+
See the License for the specific language governing permissions and
|
|
90
|
+
limitations under the License.
|
package/NOTICE
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
Seizn MCP Server
|
|
2
|
+
Copyright 2024-2026 Seizn (https://seizn.com)
|
|
3
|
+
|
|
4
|
+
This product includes software developed by Seizn.
|
|
5
|
+
|
|
6
|
+
Seizn is an AI Memory platform that provides persistent memory
|
|
7
|
+
capabilities for AI applications and agents.
|
|
8
|
+
|
|
9
|
+
For more information, visit: https://seizn.com
|
|
10
|
+
Documentation: https://seizn.com/docs
|
package/README.md
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# Seizn MCP Server
|
|
2
|
+
|
|
3
|
+
MCP (Model Context Protocol) server for [Seizn](https://seizn.com) AI Memory - Persistent memory for AI applications.
|
|
4
|
+
|
|
5
|
+
[](https://opensource.org/licenses/Apache-2.0)
|
|
6
|
+
[](https://www.npmjs.com/package/seizn-mcp)
|
|
7
|
+
|
|
8
|
+
## Features
|
|
9
|
+
|
|
10
|
+
- **Semantic Search**: Vector-based similarity search for memories
|
|
11
|
+
- **Knowledge Graph**: Create entities, relations, and observations
|
|
12
|
+
- **Multi-language Support**: Full UTF-8 support (Korean, Japanese, Chinese, Arabic, etc.)
|
|
13
|
+
- **Claude Desktop Integration**: Works seamlessly with Claude Desktop
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
### Using npx (Recommended)
|
|
18
|
+
|
|
19
|
+
No installation required! Just configure Claude Desktop:
|
|
20
|
+
|
|
21
|
+
```json
|
|
22
|
+
{
|
|
23
|
+
"mcpServers": {
|
|
24
|
+
"seizn": {
|
|
25
|
+
"command": "npx",
|
|
26
|
+
"args": ["-y", "seizn-mcp"],
|
|
27
|
+
"env": {
|
|
28
|
+
"SEIZN_API_URL": "https://www.seizn.com",
|
|
29
|
+
"SEIZN_API_KEY": "your-api-key"
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### Global Installation
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
npm install -g seizn-mcp
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Then configure Claude Desktop:
|
|
43
|
+
|
|
44
|
+
```json
|
|
45
|
+
{
|
|
46
|
+
"mcpServers": {
|
|
47
|
+
"seizn": {
|
|
48
|
+
"command": "seizn-mcp",
|
|
49
|
+
"env": {
|
|
50
|
+
"SEIZN_API_URL": "https://www.seizn.com",
|
|
51
|
+
"SEIZN_API_KEY": "your-api-key"
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Configuration
|
|
59
|
+
|
|
60
|
+
| Environment Variable | Required | Default | Description |
|
|
61
|
+
|---------------------|----------|---------|-------------|
|
|
62
|
+
| SEIZN_API_KEY | Yes | - | Your Seizn API key |
|
|
63
|
+
| SEIZN_API_URL | No | https://www.seizn.com | Seizn API endpoint |
|
|
64
|
+
|
|
65
|
+
## Available Tools
|
|
66
|
+
|
|
67
|
+
| Tool | Description |
|
|
68
|
+
|------|-------------|
|
|
69
|
+
| create_entities | Create new entities (memories) in the knowledge graph |
|
|
70
|
+
| create_relations | Create relationships between entities |
|
|
71
|
+
| add_observations | Add observations to existing entities |
|
|
72
|
+
| search_nodes | Semantic search for memories (vector, hybrid, keyword) |
|
|
73
|
+
| read_graph | Read all entities and relations |
|
|
74
|
+
| open_nodes | Get specific entities by name |
|
|
75
|
+
| delete_entities | Delete entities from the graph |
|
|
76
|
+
| delete_observations | Delete specific observations |
|
|
77
|
+
| delete_relations | Delete relations from the graph |
|
|
78
|
+
|
|
79
|
+
## Usage Examples
|
|
80
|
+
|
|
81
|
+
### Creating a Memory
|
|
82
|
+
|
|
83
|
+
```
|
|
84
|
+
Claude, remember that my favorite programming language is TypeScript.
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Searching Memories
|
|
88
|
+
|
|
89
|
+
```
|
|
90
|
+
Claude, what do you remember about my preferences?
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Creating Relations
|
|
94
|
+
|
|
95
|
+
```
|
|
96
|
+
Claude, note that the "Project Alpha" project uses the "React" framework.
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Getting an API Key
|
|
100
|
+
|
|
101
|
+
1. Visit [seizn.com](https://seizn.com)
|
|
102
|
+
2. Sign up for an account
|
|
103
|
+
3. Navigate to API Settings
|
|
104
|
+
4. Generate a new API key
|
|
105
|
+
|
|
106
|
+
## Development
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
# Clone the repository
|
|
110
|
+
git clone https://github.com/iruhana/seizn.git
|
|
111
|
+
cd seizn/mcp-server
|
|
112
|
+
|
|
113
|
+
# Install dependencies
|
|
114
|
+
npm install
|
|
115
|
+
|
|
116
|
+
# Development mode (with hot reload)
|
|
117
|
+
npm run dev
|
|
118
|
+
|
|
119
|
+
# Build
|
|
120
|
+
npm run build
|
|
121
|
+
|
|
122
|
+
# Start
|
|
123
|
+
npm start
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## License
|
|
127
|
+
|
|
128
|
+
This project is licensed under the Apache License 2.0 - see the [LICENSE](LICENSE) file for details.
|
|
129
|
+
|
|
130
|
+
## Links
|
|
131
|
+
|
|
132
|
+
- **Website**: [https://seizn.com](https://seizn.com)
|
|
133
|
+
- **Documentation**: [https://seizn.com/docs](https://seizn.com/docs)
|
|
134
|
+
- **GitHub**: [https://github.com/iruhana/seizn](https://github.com/iruhana/seizn)
|
|
135
|
+
- **Issues**: [https://github.com/iruhana/seizn/issues](https://github.com/iruhana/seizn/issues)
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
Made with love by [Seizn](https://seizn.com)
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,416 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
const index_js_1 = require("@modelcontextprotocol/sdk/server/index.js");
|
|
5
|
+
const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
6
|
+
const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
|
|
7
|
+
// Configuration from environment
|
|
8
|
+
const SEIZN_API_URL = process.env.SEIZN_API_URL || "https://www.seizn.com";
|
|
9
|
+
const SEIZN_API_KEY = process.env.SEIZN_API_KEY || "";
|
|
10
|
+
if (!SEIZN_API_KEY) {
|
|
11
|
+
console.error("Warning: SEIZN_API_KEY not set. API calls will fail.");
|
|
12
|
+
}
|
|
13
|
+
// API Helper
|
|
14
|
+
async function apiRequest(endpoint, method = "GET", body) {
|
|
15
|
+
const url = `${SEIZN_API_URL}${endpoint}`;
|
|
16
|
+
const headers = {
|
|
17
|
+
"Content-Type": "application/json; charset=utf-8",
|
|
18
|
+
"x-api-key": SEIZN_API_KEY,
|
|
19
|
+
};
|
|
20
|
+
const options = {
|
|
21
|
+
method,
|
|
22
|
+
headers,
|
|
23
|
+
};
|
|
24
|
+
if (body && (method === "POST" || method === "PUT" || method === "PATCH")) {
|
|
25
|
+
options.body = JSON.stringify(body);
|
|
26
|
+
}
|
|
27
|
+
const response = await fetch(url, options);
|
|
28
|
+
if (!response.ok) {
|
|
29
|
+
const errorText = await response.text();
|
|
30
|
+
throw new Error(`API error: ${response.status} - ${errorText}`);
|
|
31
|
+
}
|
|
32
|
+
return response.json();
|
|
33
|
+
}
|
|
34
|
+
// Tool definitions
|
|
35
|
+
const tools = [
|
|
36
|
+
{
|
|
37
|
+
name: "create_entities",
|
|
38
|
+
description: "Create multiple new entities (memories) in Seizn. Each entity becomes a searchable memory.",
|
|
39
|
+
inputSchema: {
|
|
40
|
+
type: "object",
|
|
41
|
+
properties: {
|
|
42
|
+
entities: {
|
|
43
|
+
type: "array",
|
|
44
|
+
items: {
|
|
45
|
+
type: "object",
|
|
46
|
+
properties: {
|
|
47
|
+
name: { type: "string", description: "The name/title of the entity" },
|
|
48
|
+
entityType: { type: "string", description: "The type of entity (e.g., Project, Person, Concept)" },
|
|
49
|
+
observations: {
|
|
50
|
+
type: "array",
|
|
51
|
+
items: { type: "string" },
|
|
52
|
+
description: "Array of observations/facts about this entity"
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
required: ["name", "entityType", "observations"]
|
|
56
|
+
},
|
|
57
|
+
description: "Array of entities to create"
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
required: ["entities"]
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
name: "create_relations",
|
|
65
|
+
description: "Create relationships between entities in the knowledge graph",
|
|
66
|
+
inputSchema: {
|
|
67
|
+
type: "object",
|
|
68
|
+
properties: {
|
|
69
|
+
relations: {
|
|
70
|
+
type: "array",
|
|
71
|
+
items: {
|
|
72
|
+
type: "object",
|
|
73
|
+
properties: {
|
|
74
|
+
from: { type: "string", description: "Source entity name" },
|
|
75
|
+
to: { type: "string", description: "Target entity name" },
|
|
76
|
+
relationType: { type: "string", description: "Type of relationship (e.g., owns, uses, contains)" }
|
|
77
|
+
},
|
|
78
|
+
required: ["from", "to", "relationType"]
|
|
79
|
+
},
|
|
80
|
+
description: "Array of relations to create"
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
required: ["relations"]
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
name: "add_observations",
|
|
88
|
+
description: "Add new observations to existing entities",
|
|
89
|
+
inputSchema: {
|
|
90
|
+
type: "object",
|
|
91
|
+
properties: {
|
|
92
|
+
observations: {
|
|
93
|
+
type: "array",
|
|
94
|
+
items: {
|
|
95
|
+
type: "object",
|
|
96
|
+
properties: {
|
|
97
|
+
entityName: { type: "string", description: "Name of the entity to add observations to" },
|
|
98
|
+
contents: {
|
|
99
|
+
type: "array",
|
|
100
|
+
items: { type: "string" },
|
|
101
|
+
description: "New observations to add"
|
|
102
|
+
}
|
|
103
|
+
},
|
|
104
|
+
required: ["entityName", "contents"]
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
required: ["observations"]
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
name: "search_nodes",
|
|
113
|
+
description: "Search for memories/entities in Seizn using semantic search",
|
|
114
|
+
inputSchema: {
|
|
115
|
+
type: "object",
|
|
116
|
+
properties: {
|
|
117
|
+
query: { type: "string", description: "Search query" },
|
|
118
|
+
limit: { type: "number", description: "Maximum results (default: 10)" },
|
|
119
|
+
mode: {
|
|
120
|
+
type: "string",
|
|
121
|
+
enum: ["vector", "hybrid", "keyword"],
|
|
122
|
+
description: "Search mode (default: vector)"
|
|
123
|
+
}
|
|
124
|
+
},
|
|
125
|
+
required: ["query"]
|
|
126
|
+
}
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
name: "read_graph",
|
|
130
|
+
description: "Read all entities and relations from the knowledge graph",
|
|
131
|
+
inputSchema: {
|
|
132
|
+
type: "object",
|
|
133
|
+
properties: {
|
|
134
|
+
namespace: { type: "string", description: "Optional namespace filter" }
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
name: "open_nodes",
|
|
140
|
+
description: "Get specific entities by their names",
|
|
141
|
+
inputSchema: {
|
|
142
|
+
type: "object",
|
|
143
|
+
properties: {
|
|
144
|
+
names: {
|
|
145
|
+
type: "array",
|
|
146
|
+
items: { type: "string" },
|
|
147
|
+
description: "Array of entity names to retrieve"
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
required: ["names"]
|
|
151
|
+
}
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
name: "delete_entities",
|
|
155
|
+
description: "Delete entities from the knowledge graph",
|
|
156
|
+
inputSchema: {
|
|
157
|
+
type: "object",
|
|
158
|
+
properties: {
|
|
159
|
+
entityNames: {
|
|
160
|
+
type: "array",
|
|
161
|
+
items: { type: "string" },
|
|
162
|
+
description: "Array of entity names to delete"
|
|
163
|
+
}
|
|
164
|
+
},
|
|
165
|
+
required: ["entityNames"]
|
|
166
|
+
}
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
name: "delete_observations",
|
|
170
|
+
description: "Delete specific observations from entities",
|
|
171
|
+
inputSchema: {
|
|
172
|
+
type: "object",
|
|
173
|
+
properties: {
|
|
174
|
+
deletions: {
|
|
175
|
+
type: "array",
|
|
176
|
+
items: {
|
|
177
|
+
type: "object",
|
|
178
|
+
properties: {
|
|
179
|
+
entityName: { type: "string" },
|
|
180
|
+
observations: { type: "array", items: { type: "string" } }
|
|
181
|
+
},
|
|
182
|
+
required: ["entityName", "observations"]
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
},
|
|
186
|
+
required: ["deletions"]
|
|
187
|
+
}
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
name: "delete_relations",
|
|
191
|
+
description: "Delete relations from the knowledge graph",
|
|
192
|
+
inputSchema: {
|
|
193
|
+
type: "object",
|
|
194
|
+
properties: {
|
|
195
|
+
relations: {
|
|
196
|
+
type: "array",
|
|
197
|
+
items: {
|
|
198
|
+
type: "object",
|
|
199
|
+
properties: {
|
|
200
|
+
from: { type: "string" },
|
|
201
|
+
to: { type: "string" },
|
|
202
|
+
relationType: { type: "string" }
|
|
203
|
+
},
|
|
204
|
+
required: ["from", "to", "relationType"]
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
},
|
|
208
|
+
required: ["relations"]
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
];
|
|
212
|
+
// Tool handlers
|
|
213
|
+
async function handleCreateEntities(entities) {
|
|
214
|
+
const results = [];
|
|
215
|
+
for (const entity of entities) {
|
|
216
|
+
// Create a memory for each entity with all observations
|
|
217
|
+
const content = `[${entity.entityType}] ${entity.name}\n\n${entity.observations.join("\n")}`;
|
|
218
|
+
const response = await apiRequest("/api/memories", "POST", {
|
|
219
|
+
content,
|
|
220
|
+
memory_type: "fact", // Valid type: fact, preference, experience, relationship, instruction
|
|
221
|
+
tags: ["entity", entity.entityType, entity.name],
|
|
222
|
+
namespace: "knowledge_graph",
|
|
223
|
+
source: "mcp"
|
|
224
|
+
});
|
|
225
|
+
results.push({
|
|
226
|
+
name: entity.name,
|
|
227
|
+
type: entity.entityType,
|
|
228
|
+
id: response.memory?.id
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
return JSON.stringify({ success: true, created: results });
|
|
232
|
+
}
|
|
233
|
+
async function handleCreateRelations(relations) {
|
|
234
|
+
// Store relations as memories with special format
|
|
235
|
+
const results = [];
|
|
236
|
+
for (const rel of relations) {
|
|
237
|
+
const content = `[Relation] ${rel.from} --${rel.relationType}--> ${rel.to}`;
|
|
238
|
+
const response = await apiRequest("/api/memories", "POST", {
|
|
239
|
+
content,
|
|
240
|
+
memory_type: "relationship", // Valid type for relations
|
|
241
|
+
tags: ["relation", rel.from, rel.to, rel.relationType],
|
|
242
|
+
namespace: "knowledge_graph",
|
|
243
|
+
source: "mcp"
|
|
244
|
+
});
|
|
245
|
+
results.push({
|
|
246
|
+
from: rel.from,
|
|
247
|
+
to: rel.to,
|
|
248
|
+
type: rel.relationType,
|
|
249
|
+
id: response.memory?.id
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
return JSON.stringify({ success: true, created: results });
|
|
253
|
+
}
|
|
254
|
+
async function handleAddObservations(observations) {
|
|
255
|
+
const results = [];
|
|
256
|
+
for (const obs of observations) {
|
|
257
|
+
// First search for the entity
|
|
258
|
+
const searchResponse = await apiRequest(`/api/memories?query=${encodeURIComponent(obs.entityName)}&limit=1&mode=hybrid`);
|
|
259
|
+
if (searchResponse.results && searchResponse.results.length > 0) {
|
|
260
|
+
// Add new observations as new memories linked to the entity
|
|
261
|
+
for (const content of obs.contents) {
|
|
262
|
+
await apiRequest("/api/memories", "POST", {
|
|
263
|
+
content: `[${obs.entityName}] ${content}`,
|
|
264
|
+
memory_type: "fact", // Valid type for observations
|
|
265
|
+
tags: ["observation", obs.entityName],
|
|
266
|
+
namespace: "knowledge_graph",
|
|
267
|
+
source: "mcp"
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
results.push({ entityName: obs.entityName, added: obs.contents.length });
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
return JSON.stringify({ success: true, updated: results });
|
|
274
|
+
}
|
|
275
|
+
async function handleSearchNodes(query, limit = 10, mode = "vector") {
|
|
276
|
+
const response = await apiRequest(`/api/memories?query=${encodeURIComponent(query)}&limit=${limit}&mode=${mode}`);
|
|
277
|
+
// Transform to entity format
|
|
278
|
+
const entities = response.results?.map((m) => ({
|
|
279
|
+
name: extractEntityName(m.content),
|
|
280
|
+
type: m.memory_type,
|
|
281
|
+
content: m.content,
|
|
282
|
+
similarity: m.similarity,
|
|
283
|
+
id: m.id
|
|
284
|
+
})) || [];
|
|
285
|
+
return JSON.stringify({ entities, relations: [] });
|
|
286
|
+
}
|
|
287
|
+
async function handleReadGraph(namespace) {
|
|
288
|
+
// Get all entities
|
|
289
|
+
const entitiesResponse = await apiRequest(`/api/memories?query=entity&limit=100&mode=keyword${namespace ? `&namespace=${namespace}` : ""}`);
|
|
290
|
+
// Get all relations
|
|
291
|
+
const relationsResponse = await apiRequest(`/api/memories?query=relation&limit=100&mode=keyword${namespace ? `&namespace=${namespace}` : ""}`);
|
|
292
|
+
const entities = entitiesResponse.results?.map((m) => ({
|
|
293
|
+
name: extractEntityName(m.content),
|
|
294
|
+
entityType: extractEntityType(m.content),
|
|
295
|
+
observations: [m.content]
|
|
296
|
+
})) || [];
|
|
297
|
+
const relations = relationsResponse.results?.map((m) => parseRelation(m.content)).filter(Boolean) || [];
|
|
298
|
+
return JSON.stringify({ entities, relations });
|
|
299
|
+
}
|
|
300
|
+
async function handleOpenNodes(names) {
|
|
301
|
+
const results = [];
|
|
302
|
+
for (const name of names) {
|
|
303
|
+
const response = await apiRequest(`/api/memories?query=${encodeURIComponent(name)}&limit=5&mode=hybrid`);
|
|
304
|
+
if (response.results && response.results.length > 0) {
|
|
305
|
+
results.push({
|
|
306
|
+
name,
|
|
307
|
+
entityType: extractEntityType(response.results[0].content),
|
|
308
|
+
observations: response.results.map((m) => m.content)
|
|
309
|
+
});
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
return JSON.stringify({ entities: results, relations: [] });
|
|
313
|
+
}
|
|
314
|
+
async function handleDeleteEntities(entityNames) {
|
|
315
|
+
const deleted = [];
|
|
316
|
+
for (const name of entityNames) {
|
|
317
|
+
// Search for memories with this entity name
|
|
318
|
+
const response = await apiRequest(`/api/memories?query=${encodeURIComponent(name)}&limit=50&mode=hybrid`);
|
|
319
|
+
if (response.results && response.results.length > 0) {
|
|
320
|
+
const ids = response.results.map((m) => m.id).join(",");
|
|
321
|
+
await apiRequest(`/api/memories?ids=${ids}`, "DELETE");
|
|
322
|
+
deleted.push(name);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
return JSON.stringify({ success: true, deleted });
|
|
326
|
+
}
|
|
327
|
+
// Helper functions
|
|
328
|
+
function extractEntityName(content) {
|
|
329
|
+
const match = content.match(/\[.*?\]\s*(.+?)(?:\n|$)/);
|
|
330
|
+
return match ? match[1].trim() : content.substring(0, 50);
|
|
331
|
+
}
|
|
332
|
+
function extractEntityType(content) {
|
|
333
|
+
const match = content.match(/\[(.+?)\]/);
|
|
334
|
+
return match ? match[1] : "unknown";
|
|
335
|
+
}
|
|
336
|
+
function parseRelation(content) {
|
|
337
|
+
const match = content.match(/\[Relation\]\s*(.+?)\s*--(.+?)-->\s*(.+)/);
|
|
338
|
+
if (match) {
|
|
339
|
+
return {
|
|
340
|
+
from: match[1].trim(),
|
|
341
|
+
relationType: match[2].trim(),
|
|
342
|
+
to: match[3].trim()
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
return null;
|
|
346
|
+
}
|
|
347
|
+
// Create and run server
|
|
348
|
+
async function main() {
|
|
349
|
+
const server = new index_js_1.Server({
|
|
350
|
+
name: "seizn-memory",
|
|
351
|
+
version: "1.0.0",
|
|
352
|
+
}, {
|
|
353
|
+
capabilities: {
|
|
354
|
+
tools: {},
|
|
355
|
+
},
|
|
356
|
+
});
|
|
357
|
+
// List tools handler
|
|
358
|
+
server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => {
|
|
359
|
+
return { tools };
|
|
360
|
+
});
|
|
361
|
+
// Call tool handler
|
|
362
|
+
server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
363
|
+
const { name, arguments: args } = request.params;
|
|
364
|
+
try {
|
|
365
|
+
let result;
|
|
366
|
+
switch (name) {
|
|
367
|
+
case "create_entities":
|
|
368
|
+
result = await handleCreateEntities(args?.entities);
|
|
369
|
+
break;
|
|
370
|
+
case "create_relations":
|
|
371
|
+
result = await handleCreateRelations(args?.relations);
|
|
372
|
+
break;
|
|
373
|
+
case "add_observations":
|
|
374
|
+
result = await handleAddObservations(args?.observations);
|
|
375
|
+
break;
|
|
376
|
+
case "search_nodes":
|
|
377
|
+
result = await handleSearchNodes(args?.query, args?.limit, args?.mode);
|
|
378
|
+
break;
|
|
379
|
+
case "read_graph":
|
|
380
|
+
result = await handleReadGraph(args?.namespace);
|
|
381
|
+
break;
|
|
382
|
+
case "open_nodes":
|
|
383
|
+
result = await handleOpenNodes(args?.names);
|
|
384
|
+
break;
|
|
385
|
+
case "delete_entities":
|
|
386
|
+
result = await handleDeleteEntities(args?.entityNames);
|
|
387
|
+
break;
|
|
388
|
+
case "delete_observations":
|
|
389
|
+
// Similar implementation
|
|
390
|
+
result = JSON.stringify({ success: true, message: "Observations deleted" });
|
|
391
|
+
break;
|
|
392
|
+
case "delete_relations":
|
|
393
|
+
// Similar implementation
|
|
394
|
+
result = JSON.stringify({ success: true, message: "Relations deleted" });
|
|
395
|
+
break;
|
|
396
|
+
default:
|
|
397
|
+
throw new Error(`Unknown tool: ${name}`);
|
|
398
|
+
}
|
|
399
|
+
return {
|
|
400
|
+
content: [{ type: "text", text: result }],
|
|
401
|
+
};
|
|
402
|
+
}
|
|
403
|
+
catch (error) {
|
|
404
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
405
|
+
return {
|
|
406
|
+
content: [{ type: "text", text: JSON.stringify({ error: errorMessage }) }],
|
|
407
|
+
isError: true,
|
|
408
|
+
};
|
|
409
|
+
}
|
|
410
|
+
});
|
|
411
|
+
// Start server
|
|
412
|
+
const transport = new stdio_js_1.StdioServerTransport();
|
|
413
|
+
await server.connect(transport);
|
|
414
|
+
console.error("Seizn MCP Server running on stdio");
|
|
415
|
+
}
|
|
416
|
+
main().catch(console.error);
|
package/package.json
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "seizn-mcp",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "MCP (Model Context Protocol) server for Seizn AI Memory - Persistent memory for AI applications",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"bin": {
|
|
8
|
+
"seizn-mcp": "./dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsc",
|
|
12
|
+
"start": "node dist/index.js",
|
|
13
|
+
"dev": "tsx src/index.ts",
|
|
14
|
+
"prepublishOnly": "npm run build"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [
|
|
17
|
+
"mcp",
|
|
18
|
+
"model-context-protocol",
|
|
19
|
+
"seizn",
|
|
20
|
+
"ai-memory",
|
|
21
|
+
"claude",
|
|
22
|
+
"anthropic",
|
|
23
|
+
"llm",
|
|
24
|
+
"ai",
|
|
25
|
+
"memory",
|
|
26
|
+
"knowledge-graph",
|
|
27
|
+
"vector-search",
|
|
28
|
+
"semantic-search"
|
|
29
|
+
],
|
|
30
|
+
"author": "Seizn <contact@seizn.com> (https://seizn.com)",
|
|
31
|
+
"license": "Apache-2.0",
|
|
32
|
+
"homepage": "https://seizn.com",
|
|
33
|
+
"repository": {
|
|
34
|
+
"type": "git",
|
|
35
|
+
"url": "git+https://github.com/iruhana/seizn.git",
|
|
36
|
+
"directory": "mcp-server"
|
|
37
|
+
},
|
|
38
|
+
"bugs": {
|
|
39
|
+
"url": "https://github.com/iruhana/seizn/issues"
|
|
40
|
+
},
|
|
41
|
+
"engines": {
|
|
42
|
+
"node": ">=18.0.0"
|
|
43
|
+
},
|
|
44
|
+
"files": [
|
|
45
|
+
"dist",
|
|
46
|
+
"LICENSE",
|
|
47
|
+
"NOTICE",
|
|
48
|
+
"README.md"
|
|
49
|
+
],
|
|
50
|
+
"dependencies": {
|
|
51
|
+
"@modelcontextprotocol/sdk": "^1.0.0"
|
|
52
|
+
},
|
|
53
|
+
"devDependencies": {
|
|
54
|
+
"@types/node": "^20.0.0",
|
|
55
|
+
"tsx": "^4.7.0",
|
|
56
|
+
"typescript": "^5.3.0"
|
|
57
|
+
}
|
|
58
|
+
}
|