@echomate/mcp-server 0.0.0-stage → 1.0.1
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 +21 -0
- package/README.md +61 -2
- package/SECURITY.md +21 -0
- package/dist/client.d.ts +83 -0
- package/dist/client.js +142 -0
- package/dist/client.js.map +1 -0
- package/dist/guide.d.ts +1 -0
- package/dist/guide.js +33 -0
- package/dist/guide.js.map +1 -0
- package/dist/http-server.d.ts +1 -0
- package/dist/http-server.js +115 -0
- package/dist/http-server.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +23 -0
- package/dist/index.js.map +1 -0
- package/dist/instructions.d.ts +1 -0
- package/dist/instructions.js +58 -0
- package/dist/instructions.js.map +1 -0
- package/dist/karten.d.ts +32 -0
- package/dist/karten.js +414 -0
- package/dist/karten.js.map +1 -0
- package/dist/server-info.d.ts +12 -0
- package/dist/server-info.js +12 -0
- package/dist/server-info.js.map +1 -0
- package/dist/tools.d.ts +14 -0
- package/dist/tools.js +611 -0
- package/dist/tools.js.map +1 -0
- package/dist/types.d.ts +203 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/werkzeug-referenz.d.ts +10 -0
- package/dist/werkzeug-referenz.js +35 -0
- package/dist/werkzeug-referenz.js.map +1 -0
- package/dist/werkzeuge-sammeln.d.ts +3 -0
- package/dist/werkzeuge-sammeln.js +39 -0
- package/dist/werkzeuge-sammeln.js.map +1 -0
- package/dist/zugang.d.ts +22 -0
- package/dist/zugang.js +42 -0
- package/dist/zugang.js.map +1 -0
- package/package.json +39 -4
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
export interface QRCode {
|
|
2
|
+
id: string;
|
|
3
|
+
name: string;
|
|
4
|
+
targetUrl: string;
|
|
5
|
+
shortUrl: string | null;
|
|
6
|
+
scansCount: number;
|
|
7
|
+
createdAt: string;
|
|
8
|
+
isActive?: boolean | null;
|
|
9
|
+
}
|
|
10
|
+
export interface ShortLink {
|
|
11
|
+
id: string;
|
|
12
|
+
slug: string;
|
|
13
|
+
shortUrl: string;
|
|
14
|
+
targetUrl: string;
|
|
15
|
+
clicksCount: number;
|
|
16
|
+
isActive: boolean;
|
|
17
|
+
utmSource: string | null;
|
|
18
|
+
utmMedium: string | null;
|
|
19
|
+
utmCampaign: string | null;
|
|
20
|
+
createdAt: string;
|
|
21
|
+
}
|
|
22
|
+
export interface AnalyticsOverview {
|
|
23
|
+
totalScans: number;
|
|
24
|
+
totalClicks: number;
|
|
25
|
+
totalConversions: number;
|
|
26
|
+
totalRevenue: number | null;
|
|
27
|
+
revenueCurrency: string | null;
|
|
28
|
+
revenueByCurrency: Array<{
|
|
29
|
+
currency: string;
|
|
30
|
+
total: number;
|
|
31
|
+
conversions: number;
|
|
32
|
+
}>;
|
|
33
|
+
uniqueVisitors: number;
|
|
34
|
+
topCountry: string | null;
|
|
35
|
+
}
|
|
36
|
+
export interface AiTraffic {
|
|
37
|
+
total: number;
|
|
38
|
+
percentage: number;
|
|
39
|
+
sources: Array<{
|
|
40
|
+
name: string;
|
|
41
|
+
count: number;
|
|
42
|
+
}>;
|
|
43
|
+
}
|
|
44
|
+
export interface PaginatedResponse<T> {
|
|
45
|
+
data: T[];
|
|
46
|
+
total: number;
|
|
47
|
+
page: number;
|
|
48
|
+
pageSize: number;
|
|
49
|
+
}
|
|
50
|
+
export interface BreakdownItem {
|
|
51
|
+
name: string;
|
|
52
|
+
value: number;
|
|
53
|
+
}
|
|
54
|
+
export interface DailyEvent {
|
|
55
|
+
date: string;
|
|
56
|
+
scans: number;
|
|
57
|
+
clicks: number;
|
|
58
|
+
conversions: number;
|
|
59
|
+
}
|
|
60
|
+
export interface AnalyticsResponse {
|
|
61
|
+
period: {
|
|
62
|
+
days: number;
|
|
63
|
+
from: string;
|
|
64
|
+
to: string;
|
|
65
|
+
};
|
|
66
|
+
overview: AnalyticsOverview;
|
|
67
|
+
dailyEvents: DailyEvent[];
|
|
68
|
+
deviceBreakdown: BreakdownItem[];
|
|
69
|
+
countryBreakdown: BreakdownItem[];
|
|
70
|
+
browserBreakdown: BreakdownItem[];
|
|
71
|
+
aiTraffic: AiTraffic;
|
|
72
|
+
referrerBreakdown: BreakdownItem[];
|
|
73
|
+
}
|
|
74
|
+
export interface HealthScore {
|
|
75
|
+
latestScan: {
|
|
76
|
+
performanceScore: number;
|
|
77
|
+
lcp: number | null;
|
|
78
|
+
cls: number | null;
|
|
79
|
+
fid: number | null;
|
|
80
|
+
fcp: number | null;
|
|
81
|
+
ttfb: number | null;
|
|
82
|
+
si: number | null;
|
|
83
|
+
tbt: number | null;
|
|
84
|
+
url: string;
|
|
85
|
+
scannedAt: string;
|
|
86
|
+
} | null;
|
|
87
|
+
previousScore: number | null;
|
|
88
|
+
trend: "improving" | "declining" | "stable" | null;
|
|
89
|
+
appImpacts: Array<{
|
|
90
|
+
appName: string;
|
|
91
|
+
scriptUrl: string;
|
|
92
|
+
sizeBytes: number | null;
|
|
93
|
+
loadTimeMs: number | null;
|
|
94
|
+
detectedAt: string;
|
|
95
|
+
}>;
|
|
96
|
+
}
|
|
97
|
+
export interface LinkDetail {
|
|
98
|
+
id: string;
|
|
99
|
+
slug: string;
|
|
100
|
+
shortUrl: string;
|
|
101
|
+
targetUrl: string;
|
|
102
|
+
clicksCount: number;
|
|
103
|
+
isActive: boolean;
|
|
104
|
+
utmSource: string | null;
|
|
105
|
+
utmMedium: string | null;
|
|
106
|
+
utmCampaign: string | null;
|
|
107
|
+
abVariantUrl: string | null;
|
|
108
|
+
abSplitPct: number | null;
|
|
109
|
+
expiresAt: string | null;
|
|
110
|
+
maxClicks: number | null;
|
|
111
|
+
startsAt: string | null;
|
|
112
|
+
createdAt: string;
|
|
113
|
+
analytics: {
|
|
114
|
+
period: string;
|
|
115
|
+
totalClicks: number;
|
|
116
|
+
conversions: number;
|
|
117
|
+
revenueCents: number | null;
|
|
118
|
+
clicksByDay: Array<{
|
|
119
|
+
date: string;
|
|
120
|
+
count: number;
|
|
121
|
+
}>;
|
|
122
|
+
deviceBreakdown: Array<{
|
|
123
|
+
name: string;
|
|
124
|
+
value: number;
|
|
125
|
+
}>;
|
|
126
|
+
countryBreakdown: Array<{
|
|
127
|
+
name: string;
|
|
128
|
+
value: number;
|
|
129
|
+
}>;
|
|
130
|
+
abTestResults: Record<string, {
|
|
131
|
+
clicks: number;
|
|
132
|
+
conversions: number;
|
|
133
|
+
}> | null;
|
|
134
|
+
abTestSince: string | null;
|
|
135
|
+
ruleAbTests: Array<{
|
|
136
|
+
ruleId: string;
|
|
137
|
+
since: string | null;
|
|
138
|
+
results: Record<string, {
|
|
139
|
+
clicks: number;
|
|
140
|
+
conversions: number;
|
|
141
|
+
}> | null;
|
|
142
|
+
}>;
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
export interface TopPerformers {
|
|
146
|
+
period: {
|
|
147
|
+
days: number;
|
|
148
|
+
};
|
|
149
|
+
topQRCodes: Array<{
|
|
150
|
+
id: string;
|
|
151
|
+
name: string;
|
|
152
|
+
targetUrl: string;
|
|
153
|
+
scansCount: number;
|
|
154
|
+
shortUrl: string | null;
|
|
155
|
+
}>;
|
|
156
|
+
topLinks: Array<{
|
|
157
|
+
id: string;
|
|
158
|
+
slug: string;
|
|
159
|
+
shortUrl: string;
|
|
160
|
+
targetUrl: string;
|
|
161
|
+
clicksCount: number;
|
|
162
|
+
isActive: boolean;
|
|
163
|
+
}>;
|
|
164
|
+
recentConversions: Array<{
|
|
165
|
+
linkId: string;
|
|
166
|
+
amountCents: number | null;
|
|
167
|
+
currency: string;
|
|
168
|
+
at: string;
|
|
169
|
+
}>;
|
|
170
|
+
}
|
|
171
|
+
export interface ShopSettings {
|
|
172
|
+
scanFrequency: "manual" | "daily" | "weekly";
|
|
173
|
+
alertsEnabled: boolean;
|
|
174
|
+
alertEmail: string;
|
|
175
|
+
qrDefaultFgColor: string;
|
|
176
|
+
qrDefaultBgColor: string;
|
|
177
|
+
qrDefaultLogoUrl: string | null;
|
|
178
|
+
ga4MeasurementId: string | null;
|
|
179
|
+
ga4ApiSecret: string | null;
|
|
180
|
+
fbPixelId: string | null;
|
|
181
|
+
googleAdsId: string | null;
|
|
182
|
+
}
|
|
183
|
+
export interface BioConfig {
|
|
184
|
+
enabled: boolean;
|
|
185
|
+
slug: string | null;
|
|
186
|
+
publicUrl: string | null;
|
|
187
|
+
color: string | null;
|
|
188
|
+
logoUrl: string | null;
|
|
189
|
+
linkOrder: string[];
|
|
190
|
+
}
|
|
191
|
+
export interface ShopIdentity {
|
|
192
|
+
shop_domain: string;
|
|
193
|
+
shop_name?: string;
|
|
194
|
+
plan: "Free" | "Growth" | "Pro" | "Business";
|
|
195
|
+
}
|
|
196
|
+
export interface ScanResult {
|
|
197
|
+
scanId: string;
|
|
198
|
+
performanceScore: number;
|
|
199
|
+
lcp: number | null;
|
|
200
|
+
cls: number | null;
|
|
201
|
+
url: string;
|
|
202
|
+
scannedAt: string;
|
|
203
|
+
}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export type RegistriertesWerkzeug = {
|
|
2
|
+
name: string;
|
|
3
|
+
description: string;
|
|
4
|
+
inputSchema?: Record<string, unknown>;
|
|
5
|
+
annotations: {
|
|
6
|
+
readOnlyHint?: boolean;
|
|
7
|
+
destructiveHint?: boolean;
|
|
8
|
+
};
|
|
9
|
+
};
|
|
10
|
+
export declare function werkzeugReferenz(werkzeuge: RegistriertesWerkzeug[]): string;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
function parameterZeilen(schema) {
|
|
2
|
+
if (!schema)
|
|
3
|
+
return [];
|
|
4
|
+
return Object.entries(schema).map(([name, s]) => {
|
|
5
|
+
const z = s;
|
|
6
|
+
const optional = typeof z.isOptional === "function" && z.isOptional();
|
|
7
|
+
const text = (z.description ?? "").replace(/\s+/g, " ").trim();
|
|
8
|
+
return ` - \`${name}\`${optional ? " (optional)" : ""}${text ? ` — ${text}` : ""}`;
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
function eintrag(w) {
|
|
12
|
+
const text = w.description.replace(/\s+/g, " ").trim();
|
|
13
|
+
const zeilen = [`- **\`${w.name}\`** — ${text}`];
|
|
14
|
+
return zeilen.concat(parameterZeilen(w.inputSchema));
|
|
15
|
+
}
|
|
16
|
+
export function werkzeugReferenz(werkzeuge) {
|
|
17
|
+
const sortiert = [...werkzeuge].sort((a, b) => a.name.localeCompare(b.name));
|
|
18
|
+
const lesend = sortiert.filter((w) => w.annotations.readOnlyHint);
|
|
19
|
+
const aendernd = sortiert.filter((w) => !w.annotations.readOnlyHint);
|
|
20
|
+
const aus = [];
|
|
21
|
+
aus.push("### Reads (change nothing)");
|
|
22
|
+
aus.push("");
|
|
23
|
+
for (const w of lesend)
|
|
24
|
+
aus.push(...eintrag(w));
|
|
25
|
+
aus.push("");
|
|
26
|
+
aus.push("### Changes (take effect immediately)");
|
|
27
|
+
aus.push("");
|
|
28
|
+
for (const w of aendernd) {
|
|
29
|
+
aus.push(...eintrag(w));
|
|
30
|
+
if (w.annotations.destructiveHint)
|
|
31
|
+
aus.push(" - ⚠ Cannot be undone.");
|
|
32
|
+
}
|
|
33
|
+
return aus.join("\n");
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=werkzeug-referenz.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"werkzeug-referenz.js","sourceRoot":"","sources":["../src/werkzeug-referenz.ts"],"names":[],"mappings":"AAuCA,SAAS,eAAe,CAAC,MAA2C;IAClE,IAAI,CAAC,MAAM;QAAE,OAAO,EAAE,CAAC;IACvB,OAAO,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE;QAC9C,MAAM,CAAC,GAAG,CAAa,CAAC;QACxB,MAAM,QAAQ,GAAG,OAAO,CAAC,CAAC,UAAU,KAAK,UAAU,IAAI,CAAC,CAAC,UAAU,EAAE,CAAC;QACtE,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;QAC/D,OAAO,SAAS,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;IACtF,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,OAAO,CAAC,CAAwB;IACvC,MAAM,IAAI,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IACvD,MAAM,MAAM,GAAG,CAAC,SAAS,CAAC,CAAC,IAAI,UAAU,IAAI,EAAE,CAAC,CAAC;IACjD,OAAO,MAAM,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC;AACvD,CAAC;AAMD,MAAM,UAAU,gBAAgB,CAAC,SAAkC;IACjE,MAAM,QAAQ,GAAG,CAAC,GAAG,SAAS,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IAC7E,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC;IAClE,MAAM,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC;IACrE,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,GAAG,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;IACvC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACb,KAAK,MAAM,CAAC,IAAI,MAAM;QAAE,GAAG,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;IAChD,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACb,GAAG,CAAC,IAAI,CAAC,uCAAuC,CAAC,CAAC;IAClD,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACb,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,GAAG,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;QACxB,IAAI,CAAC,CAAC,WAAW,CAAC,eAAe;YAAE,GAAG,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC;IACzE,CAAC;IACD,OAAO,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACxB,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { registerTools } from "./tools.js";
|
|
2
|
+
import { werkzeugReferenz } from "./werkzeug-referenz.js";
|
|
3
|
+
export function sammleWerkzeuge() {
|
|
4
|
+
const gesammelt = [];
|
|
5
|
+
const attrappe = {
|
|
6
|
+
registerTool: (name, meta) => {
|
|
7
|
+
gesammelt.push({ name, description: meta.description, inputSchema: meta.inputSchema, annotations: meta.annotations });
|
|
8
|
+
return undefined;
|
|
9
|
+
},
|
|
10
|
+
registerResource: () => undefined,
|
|
11
|
+
};
|
|
12
|
+
const loeschen = process.env.ECHOMATE_MCP_ALLOW_DELETE;
|
|
13
|
+
delete process.env.ECHOMATE_MCP_ALLOW_DELETE;
|
|
14
|
+
try {
|
|
15
|
+
registerTools(attrappe, { client: {}, readOnly: false });
|
|
16
|
+
}
|
|
17
|
+
finally {
|
|
18
|
+
if (loeschen !== undefined)
|
|
19
|
+
process.env.ECHOMATE_MCP_ALLOW_DELETE = loeschen;
|
|
20
|
+
}
|
|
21
|
+
return gesammelt;
|
|
22
|
+
}
|
|
23
|
+
export function toolsMd() {
|
|
24
|
+
const werkzeuge = sammleWerkzeuge();
|
|
25
|
+
return [
|
|
26
|
+
"# echomate MCP — every tool",
|
|
27
|
+
"",
|
|
28
|
+
"> **Generated** from `src/tools.ts` by `npx tsx packages/mcp-server/scripts/werkzeuge-schreiben.ts`.",
|
|
29
|
+
"> Do not edit by hand — `tests/unit-mcp-werkzeug-referenz.spec.ts` fails when this file",
|
|
30
|
+
"> no longer matches the registered tools. The same list is returned to the AI by",
|
|
31
|
+
"> `get_setup_guide`, together with the usage rules.",
|
|
32
|
+
"",
|
|
33
|
+
`Production scope: ${werkzeuge.length} tools. Deleting is off unless the installation sets \`ECHOMATE_MCP_ALLOW_DELETE=true\`.`,
|
|
34
|
+
"",
|
|
35
|
+
werkzeugReferenz(werkzeuge),
|
|
36
|
+
"",
|
|
37
|
+
].join("\n");
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=werkzeuge-sammeln.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"werkzeuge-sammeln.js","sourceRoot":"","sources":["../src/werkzeuge-sammeln.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,gBAAgB,EAA8B,MAAM,wBAAwB,CAAC;AAEtF,MAAM,UAAU,eAAe;IAC7B,MAAM,SAAS,GAA4B,EAAE,CAAC;IAC9C,MAAM,QAAQ,GAAG;QACf,YAAY,EAAE,CAAC,IAAY,EAAE,IAAuH,EAAE,EAAE;YACtJ,SAAS,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;YACtH,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,gBAAgB,EAAE,GAAG,EAAE,CAAC,SAAS;KACgB,CAAC;IACpD,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC;IACvD,OAAO,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC;IAC7C,IAAI,CAAC;QACH,aAAa,CAAC,QAAQ,EAAE,EAAE,MAAM,EAAE,EAAoB,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC;IAC7E,CAAC;YAAS,CAAC;QACT,IAAI,QAAQ,KAAK,SAAS;YAAE,OAAO,CAAC,GAAG,CAAC,yBAAyB,GAAG,QAAQ,CAAC;IAC/E,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAGD,MAAM,UAAU,OAAO;IACrB,MAAM,SAAS,GAAG,eAAe,EAAE,CAAC;IACpC,OAAO;QACL,6BAA6B;QAC7B,EAAE;QACF,sGAAsG;QACtG,yFAAyF;QACzF,kFAAkF;QAClF,qDAAqD;QACrD,EAAE;QACF,qBAAqB,SAAS,CAAC,MAAM,0FAA0F;QAC/H,EAAE;QACF,gBAAgB,CAAC,SAAS,CAAC;QAC3B,EAAE;KACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC"}
|
package/dist/zugang.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export declare const RESSOURCE = "https://api.echomate.shop/mcp";
|
|
2
|
+
export declare const SCHUTZ_METADATEN_URL = "https://api.echomate.shop/.well-known/oauth-protected-resource/mcp";
|
|
3
|
+
export type Zugang = {
|
|
4
|
+
art: "schluessel";
|
|
5
|
+
wert: string;
|
|
6
|
+
} | {
|
|
7
|
+
art: "bearer";
|
|
8
|
+
wert: string;
|
|
9
|
+
} | {
|
|
10
|
+
art: "fehlt";
|
|
11
|
+
} | {
|
|
12
|
+
art: "mehrdeutig";
|
|
13
|
+
grund: string;
|
|
14
|
+
} | {
|
|
15
|
+
art: "ungueltig";
|
|
16
|
+
grund: string;
|
|
17
|
+
};
|
|
18
|
+
type Koepfe = Record<string, string | string[] | undefined>;
|
|
19
|
+
export declare function leseZugang(koepfe: Koepfe): Zugang;
|
|
20
|
+
export declare function oauthAn(liste: string | undefined): boolean;
|
|
21
|
+
export declare function wwwAuthenticate(fehler?: "invalid_token"): string;
|
|
22
|
+
export {};
|
package/dist/zugang.js
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export const RESSOURCE = "https://api.echomate.shop/mcp";
|
|
2
|
+
export const SCHUTZ_METADATEN_URL = "https://api.echomate.shop/.well-known/oauth-protected-resource/mcp";
|
|
3
|
+
const kopf = (k, name) => {
|
|
4
|
+
const v = k[name];
|
|
5
|
+
return (Array.isArray(v) ? v[0] : v)?.trim() ?? "";
|
|
6
|
+
};
|
|
7
|
+
export function leseZugang(koepfe) {
|
|
8
|
+
const schluessel = kopf(koepfe, "x-api-key");
|
|
9
|
+
const auth = kopf(koepfe, "authorization");
|
|
10
|
+
if (schluessel && auth) {
|
|
11
|
+
return { art: "mehrdeutig", grund: "Send either X-API-Key or Authorization, not both." };
|
|
12
|
+
}
|
|
13
|
+
if (auth) {
|
|
14
|
+
const token = auth.startsWith("Bearer ") ? auth.slice(7).trim() : "";
|
|
15
|
+
if (token.startsWith("em_") || token.startsWith("qr_")) {
|
|
16
|
+
return { art: "mehrdeutig", grund: "API keys go in the X-API-Key header, not in Authorization." };
|
|
17
|
+
}
|
|
18
|
+
if (!token.startsWith("emo_at_"))
|
|
19
|
+
return { art: "ungueltig", grund: "Invalid access token." };
|
|
20
|
+
return { art: "bearer", wert: token };
|
|
21
|
+
}
|
|
22
|
+
if (schluessel) {
|
|
23
|
+
if (schluessel.startsWith("emo_")) {
|
|
24
|
+
return { art: "mehrdeutig", grund: "OAuth access tokens go in the Authorization header, not in X-API-Key." };
|
|
25
|
+
}
|
|
26
|
+
if (!schluessel.startsWith("em_") && !schluessel.startsWith("qr_")) {
|
|
27
|
+
return { art: "ungueltig", grund: "Invalid API key format. Expected em_live_... or em_test_..." };
|
|
28
|
+
}
|
|
29
|
+
return { art: "schluessel", wert: schluessel };
|
|
30
|
+
}
|
|
31
|
+
return { art: "fehlt" };
|
|
32
|
+
}
|
|
33
|
+
export function oauthAn(liste) {
|
|
34
|
+
return (liste ?? "").split(",").some((e) => e.trim() !== "");
|
|
35
|
+
}
|
|
36
|
+
export function wwwAuthenticate(fehler) {
|
|
37
|
+
const teile = [`resource_metadata="${SCHUTZ_METADATEN_URL}"`];
|
|
38
|
+
if (fehler)
|
|
39
|
+
teile.push(`error="${fehler}"`);
|
|
40
|
+
return `Bearer ${teile.join(", ")}`;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=zugang.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"zugang.js","sourceRoot":"","sources":["../src/zugang.ts"],"names":[],"mappings":"AASA,MAAM,CAAC,MAAM,SAAS,GAAG,+BAA+B,CAAC;AACzD,MAAM,CAAC,MAAM,oBAAoB,GAAG,oEAAoE,CAAC;AAWzG,MAAM,IAAI,GAAG,CAAC,CAAS,EAAE,IAAY,EAAU,EAAE;IAC/C,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;IAClB,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;AACrD,CAAC,CAAC;AAEF,MAAM,UAAU,UAAU,CAAC,MAAc;IACvC,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAC7C,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IAE3C,IAAI,UAAU,IAAI,IAAI,EAAE,CAAC;QACvB,OAAO,EAAE,GAAG,EAAE,YAAY,EAAE,KAAK,EAAE,mDAAmD,EAAE,CAAC;IAC3F,CAAC;IACD,IAAI,IAAI,EAAE,CAAC;QACT,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACrE,IAAI,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;YACvD,OAAO,EAAE,GAAG,EAAE,YAAY,EAAE,KAAK,EAAE,4DAA4D,EAAE,CAAC;QACpG,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,SAAS,CAAC;YAAE,OAAO,EAAE,GAAG,EAAE,WAAW,EAAE,KAAK,EAAE,uBAAuB,EAAE,CAAC;QAC9F,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;IACxC,CAAC;IACD,IAAI,UAAU,EAAE,CAAC;QACf,IAAI,UAAU,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;YAClC,OAAO,EAAE,GAAG,EAAE,YAAY,EAAE,KAAK,EAAE,uEAAuE,EAAE,CAAC;QAC/G,CAAC;QACD,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;YACnE,OAAO,EAAE,GAAG,EAAE,WAAW,EAAE,KAAK,EAAE,6DAA6D,EAAE,CAAC;QACpG,CAAC;QACD,OAAO,EAAE,GAAG,EAAE,YAAY,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC;IACjD,CAAC;IACD,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC;AAC1B,CAAC;AAGD,MAAM,UAAU,OAAO,CAAC,KAAyB;IAC/C,OAAO,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;AAC/D,CAAC;AAGD,MAAM,UAAU,eAAe,CAAC,MAAwB;IACtD,MAAM,KAAK,GAAG,CAAC,sBAAsB,oBAAoB,GAAG,CAAC,CAAC;IAC9D,IAAI,MAAM;QAAE,KAAK,CAAC,IAAI,CAAC,UAAU,MAAM,GAAG,CAAC,CAAC;IAC5C,OAAO,UAAU,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;AACtC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,41 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@echomate/mcp-server",
|
|
3
|
-
"version": "
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "MCP server for echomate — manage QR codes, short links, and analytics from Claude, ChatGPT, or any MCP client",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"homepage": "https://echomate.shop",
|
|
7
|
+
"bugs": {
|
|
8
|
+
"email": "security@alpin-code.de"
|
|
9
|
+
},
|
|
10
|
+
"publishConfig": {
|
|
11
|
+
"access": "public"
|
|
12
|
+
},
|
|
13
|
+
"type": "module",
|
|
14
|
+
"main": "dist/index.js",
|
|
15
|
+
"files": [
|
|
16
|
+
"dist",
|
|
17
|
+
"README.md",
|
|
18
|
+
"LICENSE",
|
|
19
|
+
"SECURITY.md"
|
|
20
|
+
],
|
|
21
|
+
"bin": {
|
|
22
|
+
"echomate-mcp": "dist/index.js"
|
|
23
|
+
},
|
|
24
|
+
"scripts": {
|
|
25
|
+
"build": "tsc",
|
|
26
|
+
"prepublishOnly": "npm run build",
|
|
27
|
+
"dev": "tsc --watch",
|
|
28
|
+
"start": "node dist/index.js"
|
|
29
|
+
},
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"@modelcontextprotocol/sdk": "^1.12.0",
|
|
32
|
+
"zod": "^3.23.0"
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"typescript": "^5.7.0",
|
|
36
|
+
"@types/node": "^22.0.0"
|
|
37
|
+
},
|
|
38
|
+
"engines": {
|
|
39
|
+
"node": ">=18"
|
|
40
|
+
}
|
|
41
|
+
}
|