chore: clean up historical scripts, add MCP configurations, update agent rules

This commit is contained in:
2026-07-08 14:13:58 -06:00
parent a2908167e6
commit 52470a44cb
52 changed files with 2181 additions and 2328 deletions
+249
View File
@@ -0,0 +1,249 @@
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
import pg from 'pg';
const server = new Server(
{
name: "shopify-mcp-server",
version: "1.0.0",
},
{
capabilities: {
tools: {},
},
}
);
// Helper to get Shopify credentials from Odoo Database
async function getShopifyCredentials() {
const client = new pg.Client({
host: '172.18.0.2',
port: 5432,
user: 'odoo',
password: 'odoo',
database: 'hazard_new'
});
try {
await client.connect();
const res = await client.query('SELECT access_token, shop_url FROM shopify_config LIMIT 1;');
if (res.rows.length === 0) {
throw new Error("No Shopify configuration found in database.");
}
return {
accessToken: res.rows[0].access_token,
shopUrl: res.rows[0].shop_url
};
} finally {
await client.end();
}
}
// Define available tools
server.setRequestHandler(ListToolsRequestSchema, async () => {
return {
tools: [
{
name: "shopify_get_order",
description: "Retrieve a complete Shopify order JSON by its order name (e.g., 4854)",
inputSchema: {
type: "object",
properties: {
order_name: {
type: "string",
description: "The order number/name without the # (e.g. 4854)",
},
},
required: ["order_name"],
},
},
{
name: "shopify_get_product_by_sku",
description: "Retrieve product variants from Shopify matching a specific SKU",
inputSchema: {
type: "object",
properties: {
sku: {
type: "string",
description: "The SKU of the product variant",
},
},
required: ["sku"],
},
},
{
name: "shopify_get_inventory_by_sku",
description: "Retrieve inventory levels across all locations for a specific SKU",
inputSchema: {
type: "object",
properties: {
sku: {
type: "string",
description: "The SKU of the product variant",
},
},
required: ["sku"],
},
},
{
name: "shopify_get_order_transactions",
description: "Retrieve the financial transactions (payments/refunds) for an order by its name (e.g., 4854)",
inputSchema: {
type: "object",
properties: {
order_name: {
type: "string",
description: "The order number/name without the # (e.g. 4854)",
},
},
required: ["order_name"],
},
}
],
};
});
// Handle tool execution
server.setRequestHandler(CallToolRequestSchema, async (request) => {
try {
const creds = await getShopifyCredentials();
const headers = {
"X-Shopify-Access-Token": creds.accessToken,
"Content-Type": "application/json"
};
const baseUrl = `https://${creds.shopUrl}/admin/api/2023-04`;
switch (request.params.name) {
case "shopify_get_order": {
const orderName = String(request.params.arguments.order_name).replace('#', '');
const response = await fetch(`${baseUrl}/orders.json?name=${orderName}&status=any`, { headers });
const data = await response.json();
if (!data.orders || data.orders.length === 0) {
return {
content: [{ type: "text", text: `Order ${orderName} not found.` }],
isError: true,
};
}
return {
content: [{ type: "text", text: JSON.stringify(data.orders[0], null, 2) }],
};
}
case "shopify_get_product_by_sku": {
const sku = String(request.params.arguments.sku);
const query = `
{
productVariants(first: 5, query: "sku:${sku}") {
edges {
node {
id
title
sku
inventoryQuantity
product {
title
}
}
}
}
}
`;
const response = await fetch(`${baseUrl}/graphql.json`, {
method: 'POST',
headers,
body: JSON.stringify({ query })
});
const data = await response.json();
return {
content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
};
}
case "shopify_get_inventory_by_sku": {
const sku = String(request.params.arguments.sku);
const query = `
{
productVariants(first: 5, query: "sku:${sku}") {
edges {
node {
sku
inventoryItem {
inventoryLevels(first: 10) {
edges {
node {
quantities(names: ["available"]) {
name
quantity
}
location {
id
name
}
}
}
}
}
}
}
}
}
`;
const response = await fetch(`${baseUrl}/graphql.json`, {
method: 'POST',
headers,
body: JSON.stringify({ query })
});
const data = await response.json();
return {
content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
};
}
case "shopify_get_order_transactions": {
const orderName = String(request.params.arguments.order_name).replace('#', '');
// First get the order ID
const orderResp = await fetch(`${baseUrl}/orders.json?name=${orderName}&status=any&fields=id,name`, { headers });
const orderData = await orderResp.json();
if (!orderData.orders || orderData.orders.length === 0) {
return {
content: [{ type: "text", text: `Order ${orderName} not found.` }],
isError: true,
};
}
const orderId = orderData.orders[0].id;
const transResp = await fetch(`${baseUrl}/orders/${orderId}/transactions.json`, { headers });
const transData = await transResp.json();
return {
content: [{ type: "text", text: JSON.stringify(transData, null, 2) }],
};
}
default:
throw new Error(`Unknown tool: ${request.params.name}`);
}
} catch (error) {
return {
content: [{ type: "text", text: `Error: ${error.message}` }],
isError: true,
};
}
});
// Run the server using stdio transport
async function run() {
const transport = new StdioServerTransport();
await server.connect(transport);
console.error("Shopify MCP Server running on stdio");
}
run().catch((error) => {
console.error("Server error:", error);
process.exit(1);
});