mirror of
https://github.com/eliasstepanik/core.git
synced 2026-01-11 18:38:27 +00:00
fix: source is not passed to memory tools
This commit is contained in:
parent
ebf9a0b05e
commit
5d3bdf9bca
@ -78,7 +78,7 @@ export function McpSourcesStats({
|
||||
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="text-lg">Current Active</CardTitle>
|
||||
<CardTitle className="text-lg">Active</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="px-3 pb-4">
|
||||
{activeSources.length === 0 ? (
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { useEffect, useRef } from "react";
|
||||
import {
|
||||
InfiniteLoader,
|
||||
AutoSizer,
|
||||
@ -10,11 +10,7 @@ import {
|
||||
import { type McpSessionItem } from "~/hooks/use-mcp-sessions";
|
||||
import { ScrollManagedList } from "../virtualized-list";
|
||||
import { Badge } from "../ui/badge";
|
||||
import { Input } from "../ui/input";
|
||||
import { Button } from "../ui/button";
|
||||
import { Check, Copy } from "lucide-react";
|
||||
import { cn } from "~/lib/utils";
|
||||
import { Card, CardContent } from "../ui/card";
|
||||
import { getIconForAuthorise } from "../icon-utils";
|
||||
|
||||
interface VirtualMcpSessionsListProps {
|
||||
@ -25,81 +21,6 @@ interface VirtualMcpSessionsListProps {
|
||||
height?: number;
|
||||
}
|
||||
|
||||
export function MCPUrlBox() {
|
||||
const [copied, setCopied] = useState(false);
|
||||
const [selectedSource, setSelectedSource] = useState<
|
||||
"Claude" | "Cursor" | "Other"
|
||||
>("Claude");
|
||||
|
||||
const getMcpURL = (source: "Claude" | "Cursor" | "Other") => {
|
||||
const baseUrl = "https://core.heysol.ai/api/v1/mcp";
|
||||
return `${baseUrl}?source=${source}`;
|
||||
};
|
||||
|
||||
const mcpURL = getMcpURL(selectedSource);
|
||||
|
||||
const copyToClipboard = async () => {
|
||||
try {
|
||||
await navigator.clipboard.writeText(mcpURL);
|
||||
setCopied(true);
|
||||
setTimeout(() => setCopied(false), 2000);
|
||||
} catch (err) {
|
||||
console.error("Failed to copy:", err);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Card className="min-w-[400px] rounded-lg bg-transparent pt-1">
|
||||
<CardContent className="pt-2 text-base">
|
||||
<div className="space-y-4">
|
||||
<div className="space-y-3">
|
||||
<div className="bg-grayAlpha-100 flex space-x-1 rounded-lg p-1">
|
||||
{(["Claude", "Cursor", "Other"] as const).map((source) => (
|
||||
<Button
|
||||
key={source}
|
||||
onClick={() => setSelectedSource(source)}
|
||||
variant="ghost"
|
||||
className={cn(
|
||||
"flex-1 rounded-md px-3 py-1.5 transition-all",
|
||||
selectedSource === source
|
||||
? "bg-accent text-accent-foreground shadow-sm"
|
||||
: "text-muted-foreground hover:text-foreground",
|
||||
)}
|
||||
>
|
||||
{source}
|
||||
</Button>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="bg-background-3 flex items-center rounded">
|
||||
<Input
|
||||
type="text"
|
||||
id="mcpURL"
|
||||
value={mcpURL}
|
||||
readOnly
|
||||
className="bg-background-3 block w-full text-base"
|
||||
/>
|
||||
<Button
|
||||
type="button"
|
||||
variant="link"
|
||||
size="sm"
|
||||
onClick={copyToClipboard}
|
||||
className="px-3"
|
||||
>
|
||||
{copied ? (
|
||||
<Check className="h-4 w-4" />
|
||||
) : (
|
||||
<Copy className="h-4 w-4" />
|
||||
)}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
function McpSessionItemRenderer(
|
||||
props: ListRowProps,
|
||||
sessions: McpSessionItem[],
|
||||
|
||||
@ -1,10 +1,7 @@
|
||||
import { useState } from "react";
|
||||
import { useMcpSessions } from "~/hooks/use-mcp-sessions";
|
||||
import { McpSessionsFilters } from "~/components/mcp/mcp-sessions-filters";
|
||||
import {
|
||||
MCPUrlBox,
|
||||
VirtualMcpSessionsList,
|
||||
} from "~/components/mcp/virtual-mcp-sessions-list";
|
||||
import { VirtualMcpSessionsList } from "~/components/mcp/virtual-mcp-sessions-list";
|
||||
import { McpSourcesStats } from "~/components/mcp/mcp-sources-stats";
|
||||
import { Card, CardContent } from "~/components/ui/card";
|
||||
import { Database, LoaderCircle } from "lucide-react";
|
||||
@ -35,7 +32,6 @@ export default function McpSettings() {
|
||||
<div className="flex h-[calc(100vh_-_135px)] w-full flex-col items-center space-y-6">
|
||||
{/* Top Sources Stats */}
|
||||
<div className="flex w-full flex-col gap-4">
|
||||
<MCPUrlBox />
|
||||
<McpSourcesStats
|
||||
sources={availableSources}
|
||||
activeSources={activeSources}
|
||||
|
||||
@ -13,17 +13,20 @@ import { IntegrationLoader } from "~/utils/mcp/integration-loader";
|
||||
import { callMemoryTool, memoryTools } from "~/utils/mcp/memory";
|
||||
import { logger } from "~/services/logger.service";
|
||||
import { type Response, type Request } from "express";
|
||||
import { getUser } from "./session.server";
|
||||
import { getUserById } from "~/models/user.server";
|
||||
import { getWorkspaceByUser } from "~/models/workspace.server";
|
||||
|
||||
const QueryParams = z.object({
|
||||
source: z.string().optional(),
|
||||
integrations: z.string().optional(), // comma-separated slugs
|
||||
no_integrations: z.boolean().optional(), // comma-separated slugs
|
||||
});
|
||||
|
||||
// Create MCP server with memory tools + dynamic integration tools
|
||||
async function createMcpServer(userId: string, sessionId: string) {
|
||||
async function createMcpServer(
|
||||
userId: string,
|
||||
sessionId: string,
|
||||
source: string,
|
||||
) {
|
||||
const server = new Server(
|
||||
{
|
||||
name: "core-unified-mcp-server",
|
||||
@ -58,7 +61,7 @@ async function createMcpServer(userId: string, sessionId: string) {
|
||||
|
||||
// Handle memory tools
|
||||
if (name.startsWith("memory_")) {
|
||||
return await callMemoryTool(name, args, userId);
|
||||
return await callMemoryTool(name, args, userId, source);
|
||||
}
|
||||
|
||||
// Handle integration tools (prefixed with integration slug)
|
||||
@ -93,6 +96,7 @@ async function createTransport(
|
||||
sessionId: string,
|
||||
source: string,
|
||||
integrations: string[],
|
||||
noIntegrations: boolean,
|
||||
userId: string,
|
||||
workspaceId: string,
|
||||
): Promise<StreamableHTTPServerTransport> {
|
||||
@ -136,7 +140,7 @@ async function createTransport(
|
||||
logger.error("Failed to send keep-alive ping, cleaning up interval." + e);
|
||||
clearInterval(keepAlive);
|
||||
}
|
||||
}, 60000); // Send ping every 60 seconds
|
||||
}, 30000); // Send ping every 60 seconds
|
||||
|
||||
// Setup cleanup on close
|
||||
transport.onclose = async () => {
|
||||
@ -147,24 +151,26 @@ async function createTransport(
|
||||
|
||||
// Load integration transports
|
||||
try {
|
||||
const result = await IntegrationLoader.loadIntegrationTransports(
|
||||
sessionId,
|
||||
userId,
|
||||
workspaceId,
|
||||
integrations.length > 0 ? integrations : undefined,
|
||||
);
|
||||
logger.log(
|
||||
`Loaded ${result.loaded} integration transports for session ${sessionId}`,
|
||||
);
|
||||
if (result.failed.length > 0) {
|
||||
logger.warn(`Failed to load some integrations: ${result.failed}`);
|
||||
if (noIntegrations) {
|
||||
const result = await IntegrationLoader.loadIntegrationTransports(
|
||||
sessionId,
|
||||
userId,
|
||||
workspaceId,
|
||||
integrations.length > 0 ? integrations : undefined,
|
||||
);
|
||||
logger.log(
|
||||
`Loaded ${result.loaded} integration transports for session ${sessionId}`,
|
||||
);
|
||||
if (result.failed.length > 0) {
|
||||
logger.warn(`Failed to load some integrations: ${result.failed}`);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error(`Error loading integration transports: ${error}`);
|
||||
}
|
||||
|
||||
// Create and connect MCP server
|
||||
const server = await createMcpServer(userId, sessionId);
|
||||
const server = await createMcpServer(userId, sessionId, source);
|
||||
await server.connect(transport);
|
||||
|
||||
return transport;
|
||||
@ -183,6 +189,8 @@ export const handleMCPRequest = async (
|
||||
? queryParams.integrations.split(",").map((s) => s.trim())
|
||||
: [];
|
||||
|
||||
const noIntegrations = queryParams.no_integrations ?? false;
|
||||
|
||||
const userId = authentication.userId;
|
||||
const workspace = await getWorkspaceByUser(userId);
|
||||
const workspaceId = workspace?.id as string;
|
||||
@ -206,6 +214,7 @@ export const handleMCPRequest = async (
|
||||
sessionId,
|
||||
sessionDetails.source,
|
||||
sessionDetails.integrations,
|
||||
noIntegrations,
|
||||
userId,
|
||||
workspaceId,
|
||||
);
|
||||
@ -222,6 +231,7 @@ export const handleMCPRequest = async (
|
||||
currentSessionId,
|
||||
source,
|
||||
integrations,
|
||||
noIntegrations,
|
||||
userId,
|
||||
workspaceId,
|
||||
);
|
||||
|
||||
@ -66,13 +66,14 @@ export async function callMemoryTool(
|
||||
toolName: string,
|
||||
args: any,
|
||||
userId: string,
|
||||
source: string,
|
||||
) {
|
||||
try {
|
||||
switch (toolName) {
|
||||
case "memory_ingest":
|
||||
return await handleMemoryIngest({ ...args, userId });
|
||||
return await handleMemoryIngest({ ...args, userId, source });
|
||||
case "memory_search":
|
||||
return await handleMemorySearch({ ...args, userId });
|
||||
return await handleMemorySearch({ ...args, userId, source });
|
||||
case "memory_get_spaces":
|
||||
return await handleMemoryGetSpaces(userId);
|
||||
default:
|
||||
|
||||
@ -82,6 +82,7 @@ export class MCPSessionManager {
|
||||
id: session.id,
|
||||
source: session.source,
|
||||
integrations: session.integrations,
|
||||
noIntegrations: session.noIntegrations,
|
||||
createdAt: session.createdAt,
|
||||
deleted: session.deleted || undefined,
|
||||
workspaceId: session.workspaceId || undefined,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user