mirror of
https://github.com/orangecoding/fredy.git
synced 2026-06-16 12:31:07 +00:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
34c4de7267 | ||
|
|
b64a118a18 | ||
|
|
03cb4d18cb |
@@ -159,7 +159,7 @@ Jobs run automatically at the interval you configure (see
|
|||||||
Starting with **V20**, Fredy ships with a built-in **MCP Server **. This allows you to connect Fredy to LLMs (like Claude, ChatGPT, or local models via LM Studio) and query your real estate data using natural language.
|
Starting with **V20**, Fredy ships with a built-in **MCP Server **. This allows you to connect Fredy to LLMs (like Claude, ChatGPT, or local models via LM Studio) and query your real estate data using natural language.
|
||||||
The local LLM can even enrich existing listings by checking the listing online.
|
The local LLM can even enrich existing listings by checking the listing online.
|
||||||
|
|
||||||
For more information on how to set it up and use it, please refer to the [MCP Readme](mcp/README.md).
|
For more information on how to set it up and use it, please refer to the [MCP Readme](lib/mcp/README.md).
|
||||||
|
|
||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ import { getSettings } from '../services/storage/settingsStorage.js';
|
|||||||
import { dashboardRouter } from './routes/dashboardRouter.js';
|
import { dashboardRouter } from './routes/dashboardRouter.js';
|
||||||
import { backupRouter } from './routes/backupRouter.js';
|
import { backupRouter } from './routes/backupRouter.js';
|
||||||
import { trackingRouter } from './routes/trackingRoute.js';
|
import { trackingRouter } from './routes/trackingRoute.js';
|
||||||
import { registerMcpRoutes } from '../../mcp/mcpHttpRoute.js';
|
import { registerMcpRoutes } from '../mcp/mcpHttpRoute.js';
|
||||||
const service = restana();
|
const service = restana();
|
||||||
const staticService = files(path.join(getDirName(), '../ui/public'));
|
const staticService = files(path.join(getDirName(), '../ui/public'));
|
||||||
const PORT = (await getSettings()).port || 9998;
|
const PORT = (await getSettings()).port || 9998;
|
||||||
|
|||||||
@@ -9,8 +9,8 @@
|
|||||||
*/
|
*/
|
||||||
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
import { queryJobs, getJob } from '../lib/services/storage/jobStorage.js';
|
import { queryJobs, getJob } from '../services/storage/jobStorage.js';
|
||||||
import { queryListings, getListingById } from '../lib/services/storage/listingsStorage.js';
|
import { queryListings, getListingById } from '../services/storage/listingsStorage.js';
|
||||||
import { authenticateToolCall, checkJobAccess } from './mcpAuthentication.js';
|
import { authenticateToolCall, checkJobAccess } from './mcpAuthentication.js';
|
||||||
import {
|
import {
|
||||||
normalizeListJobs,
|
normalizeListJobs,
|
||||||
@@ -10,7 +10,7 @@
|
|||||||
* and HTTP requests. Ensures consistent access control across all transports.
|
* and HTTP requests. Ensures consistent access control across all transports.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { getUser, validateMcpToken } from '../lib/services/storage/userStorage.js';
|
import { getUser, validateMcpToken } from '../services/storage/userStorage.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Authenticate an MCP tool call by extracting and validating the user from authInfo.
|
* Authenticate an MCP tool call by extracting and validating the user from authInfo.
|
||||||
@@ -10,7 +10,7 @@
|
|||||||
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
|
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
|
||||||
import { createMcpServer } from './mcpAdapter.js';
|
import { createMcpServer } from './mcpAdapter.js';
|
||||||
import { authenticateRequest } from './mcpAuthentication.js';
|
import { authenticateRequest } from './mcpAuthentication.js';
|
||||||
import logger from '../lib/services/logger.js';
|
import logger from '../services/logger.js';
|
||||||
import crypto from 'crypto';
|
import crypto from 'crypto';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -3,12 +3,10 @@
|
|||||||
* Licensed under Apache-2.0 with Commons Clause and Attribution/Naming Clause
|
* Licensed under Apache-2.0 with Commons Clause and Attribution/Naming Clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#!/usr/bin/env node
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2026 by Christian Kellner.
|
* Copyright (c) 2026 by Christian Kellner.
|
||||||
* Licensed under Apache-2.0 with Commons Clause and Attribution/Naming Clause
|
* Licensed under Apache-2.0 with Commons Clause and Attribution/Naming Clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fredy MCP Server – stdio transport
|
* Fredy MCP Server – stdio transport
|
||||||
*
|
*
|
||||||
@@ -24,15 +22,15 @@
|
|||||||
import { fileURLToPath } from 'url';
|
import { fileURLToPath } from 'url';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
||||||
import SqliteConnection from '../lib/services/storage/SqliteConnection.js';
|
import SqliteConnection from '../services/storage/SqliteConnection.js';
|
||||||
import { runMigrations } from '../lib/services/storage/migrations/migrate.js';
|
import { runMigrations } from '../services/storage/migrations/migrate.js';
|
||||||
import { createMcpServer } from './mcpAdapter.js';
|
import { createMcpServer } from './mcpAdapter.js';
|
||||||
import { validateMcpToken } from '../lib/services/storage/userStorage.js';
|
import { validateMcpToken } from '../services/storage/userStorage.js';
|
||||||
|
|
||||||
// Ensure cwd is the project root so that relative DB/config paths resolve correctly
|
// Ensure cwd is the project root so that relative DB/config paths resolve correctly
|
||||||
// (LM Studio and other MCP hosts may spawn this process from an arbitrary directory)
|
// (LM Studio and other MCP hosts may spawn this process from an arbitrary directory)
|
||||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||||
process.chdir(path.resolve(__dirname, '..'));
|
process.chdir(path.resolve(__dirname, '..', '..'));
|
||||||
|
|
||||||
// Initialize the database (required for standalone usage)
|
// Initialize the database (required for standalone usage)
|
||||||
await SqliteConnection.init();
|
await SqliteConnection.init();
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "fredy",
|
"name": "fredy",
|
||||||
"version": "20.0.0",
|
"version": "20.0.2",
|
||||||
"description": "[F]ind [R]eal [E]states [d]amn eas[y].",
|
"description": "[F]ind [R]eal [E]states [d]amn eas[y].",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"prepare": "husky",
|
"prepare": "husky",
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
"test": "node --import ./test/esmock-loader.mjs ./node_modules/mocha/bin/mocha.js --timeout 60000 test/**/*.test.js",
|
"test": "node --import ./test/esmock-loader.mjs ./node_modules/mocha/bin/mocha.js --timeout 60000 test/**/*.test.js",
|
||||||
"testGH": "node --import ./test/esmock-loader.mjs ./node_modules/mocha/bin/mocha.js --timeout 60000 --exclude test/provider/immonet.test.js --exclude test/provider/immobilienDe.test.js --exclude test/provider/immowelt.test.js test/**/*.test.js",
|
"testGH": "node --import ./test/esmock-loader.mjs ./node_modules/mocha/bin/mocha.js --timeout 60000 --exclude test/provider/immonet.test.js --exclude test/provider/immobilienDe.test.js --exclude test/provider/immowelt.test.js test/**/*.test.js",
|
||||||
"lint": "eslint .",
|
"lint": "eslint .",
|
||||||
"mcp:stdio": "node mcp/stdio.js",
|
"mcp:stdio": "node lib/mcp/stdio.js",
|
||||||
"lint:fix": "yarn lint --fix",
|
"lint:fix": "yarn lint --fix",
|
||||||
"migratedb": "node lib/services/storage/migrations/migrate.js",
|
"migratedb": "node lib/services/storage/migrations/migrate.js",
|
||||||
"migratedb:overwrite": "x-var MIGRATION_ALLOW_CHECKSUM_UPDATE=true node lib/services/storage/migrations/migrate.js",
|
"migratedb:overwrite": "x-var MIGRATION_ALLOW_CHECKSUM_UPDATE=true node lib/services/storage/migrations/migrate.js",
|
||||||
@@ -67,7 +67,7 @@
|
|||||||
"@mapbox/mapbox-gl-draw": "^1.5.1",
|
"@mapbox/mapbox-gl-draw": "^1.5.1",
|
||||||
"@sendgrid/mail": "8.1.6",
|
"@sendgrid/mail": "8.1.6",
|
||||||
"@vitejs/plugin-react": "5.1.4",
|
"@vitejs/plugin-react": "5.1.4",
|
||||||
"@modelcontextprotocol/sdk": "^1.27.0",
|
"@modelcontextprotocol/sdk": "^1.27.1",
|
||||||
"adm-zip": "^0.5.16",
|
"adm-zip": "^0.5.16",
|
||||||
"better-sqlite3": "^12.6.2",
|
"better-sqlite3": "^12.6.2",
|
||||||
"body-parser": "2.2.2",
|
"body-parser": "2.2.2",
|
||||||
@@ -119,7 +119,7 @@
|
|||||||
"history": "5.3.0",
|
"history": "5.3.0",
|
||||||
"husky": "9.1.7",
|
"husky": "9.1.7",
|
||||||
"less": "4.5.1",
|
"less": "4.5.1",
|
||||||
"lint-staged": "16.3.2",
|
"lint-staged": "16.3.3",
|
||||||
"mocha": "11.7.5",
|
"mocha": "11.7.5",
|
||||||
"nodemon": "^3.1.14",
|
"nodemon": "^3.1.14",
|
||||||
"prettier": "3.8.1"
|
"prettier": "3.8.1"
|
||||||
|
|||||||
16
yarn.lock
16
yarn.lock
@@ -1482,10 +1482,10 @@
|
|||||||
unist-util-visit "^5.0.0"
|
unist-util-visit "^5.0.0"
|
||||||
vfile "^6.0.0"
|
vfile "^6.0.0"
|
||||||
|
|
||||||
"@modelcontextprotocol/sdk@^1.27.0":
|
"@modelcontextprotocol/sdk@^1.27.1":
|
||||||
version "1.27.0"
|
version "1.27.1"
|
||||||
resolved "https://registry.yarnpkg.com/@modelcontextprotocol/sdk/-/sdk-1.27.0.tgz#be49d98984d703caf7804ad4de1467a739f24e65"
|
resolved "https://registry.yarnpkg.com/@modelcontextprotocol/sdk/-/sdk-1.27.1.tgz#a602cf823bf8a68e13e7112f50aeb02b09fb83b9"
|
||||||
integrity sha512-qOdO524oPMkUsOJTrsH9vz/HN3B5pKyW+9zIW51A9kDMVe7ON70drz1ouoyoyOcfzc+oxhkQ6jWmbyKnlWmYqA==
|
integrity sha512-sr6GbP+4edBwFndLbM60gf07z0FQ79gaExpnsjMGePXqFcSSb7t6iscpjk9DhFhwd+mTEQrzNafGP8/iGGFYaA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@hono/node-server" "^1.19.9"
|
"@hono/node-server" "^1.19.9"
|
||||||
ajv "^8.17.1"
|
ajv "^8.17.1"
|
||||||
@@ -4952,10 +4952,10 @@ linkifyjs@^4.3.2:
|
|||||||
resolved "https://registry.yarnpkg.com/linkifyjs/-/linkifyjs-4.3.2.tgz#d97eb45419aabf97ceb4b05a7adeb7b8c8ade2b1"
|
resolved "https://registry.yarnpkg.com/linkifyjs/-/linkifyjs-4.3.2.tgz#d97eb45419aabf97ceb4b05a7adeb7b8c8ade2b1"
|
||||||
integrity sha512-NT1CJtq3hHIreOianA8aSXn6Cw0JzYOuDQbOrSPe7gqFnCpKP++MQe3ODgO3oh2GJFORkAAdqredOa60z63GbA==
|
integrity sha512-NT1CJtq3hHIreOianA8aSXn6Cw0JzYOuDQbOrSPe7gqFnCpKP++MQe3ODgO3oh2GJFORkAAdqredOa60z63GbA==
|
||||||
|
|
||||||
lint-staged@16.3.2:
|
lint-staged@16.3.3:
|
||||||
version "16.3.2"
|
version "16.3.3"
|
||||||
resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-16.3.2.tgz#378b48c6c340d42eefcc8d13d198b61a562e63a9"
|
resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-16.3.3.tgz#ce5c95b5623cca295f8f4251f00c0642c7e84976"
|
||||||
integrity sha512-xKqhC2AeXLwiAHXguxBjuChoTTWFC6Pees0SHPwOpwlvI3BH7ZADFPddAdN3pgo3aiKgPUx/bxE78JfUnxQnlg==
|
integrity sha512-RLq2koZ5fGWrx7tcqx2tSTMQj4lRkfNJaebO/li/uunhCJbtZqwTuwPHpgIimAHHi/2nZIiGrkCHDCOeR1onxA==
|
||||||
dependencies:
|
dependencies:
|
||||||
commander "^14.0.3"
|
commander "^14.0.3"
|
||||||
listr2 "^9.0.5"
|
listr2 "^9.0.5"
|
||||||
|
|||||||
Reference in New Issue
Block a user