mgbam commited on
Commit
936bec2
Β·
verified Β·
1 Parent(s): 1832f28

Update mcp_server.py

Browse files
Files changed (1) hide show
  1. mcp_server.py +173 -28
mcp_server.py CHANGED
@@ -1,20 +1,56 @@
1
  """
2
  mcp_server.py – MCP tool server exposing:
3
- β€’ query_database – built-in SQLite demo
4
- β€’ query_hubspot – HubSpot CRM via CData Python connector
 
 
 
 
 
 
 
 
 
 
 
 
 
5
  """
6
 
 
 
 
 
7
  from mcp.server.fastmcp import FastMCP
8
- import sqlite3, json, os
9
- from cdata.hubspot import connect # pip install cdata-hubspot
10
 
11
- # ─── 1. FastMCP instance ────────────────────────────────────────────────
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
  mcp = FastMCP("EnterpriseData")
13
 
14
- # ─── 2. In-memory SQLite sample ─────────────────────────────────────────
15
  conn = sqlite3.connect(":memory:", check_same_thread=False)
16
  cur = conn.cursor()
17
-
18
  cur.execute("""
19
  CREATE TABLE Customers (
20
  CustomerID INTEGER PRIMARY KEY AUTOINCREMENT,
@@ -35,7 +71,6 @@ cur.executemany(
35
  )
36
  conn.commit()
37
 
38
- # ─── 3. SQLite tool ─────────────────────────────────────────────────────
39
  @mcp.tool()
40
  def query_database(sql: str) -> str:
41
  """Run SQL against the in-memory Customers table and return JSON rows."""
@@ -44,33 +79,143 @@ def query_database(sql: str) -> str:
44
  cols = [d[0] for d in cur.description or []]
45
  rows = [dict(zip(cols, r)) for r in cur.fetchall()]
46
  return json.dumps(rows)
47
- except Exception as exc:
48
- return json.dumps({"error": str(exc)})
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
49
 
50
- # ─── 4. HubSpot connector setup ─────────────────────────────────────────
51
- # Uses CData’s HubSpot Python connector :contentReference[oaicite:4]{index=4}
52
- HUBSPOT_TOKEN = os.getenv("HUBSPOT_TOKEN")
53
- hs_conn = connect(PrivateAppToken=HUBSPOT_TOKEN)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
54
 
55
- # ─── 5. HubSpot tool ────────────────────────────────────────────────────
56
  @mcp.tool()
57
- def query_hubspot(sql: str) -> str:
58
  """
59
- Execute SQL/ODBC-style queries on HubSpot objects (Contacts, Deals, etc.).
60
- Example:
61
- SELECT firstname, lastname, email
62
- FROM contacts
63
- WHERE lifecyclestage = 'lead';
64
  """
65
  try:
66
- cur_hs = hs_conn.cursor()
67
- cur_hs.execute(sql)
68
- cols = [d[0] for d in cur_hs.description or []]
69
- rows = [dict(zip(cols, r)) for r in cur_hs.fetchall()]
 
 
70
  return json.dumps(rows)
71
- except Exception as exc:
72
- return json.dumps({"error": str(exc)})
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
73
 
74
- # ─── 6. Run the server ───────────────────────────────────────────────────
75
  if __name__ == "__main__":
76
  mcp.run(transport="stdio")
 
1
  """
2
  mcp_server.py – MCP tool server exposing:
3
+ β€’ query_database – SQLite sample
4
+ β€’ query_salesforce – Salesforce via simple-salesforce
5
+ β€’ query_hubspot – HubSpot via hubspot-api-client
6
+ β€’ query_quickbooks – QuickBooks Online via python-quickbooks
7
+ β€’ query_stripe – Stripe via stripe
8
+ β€’ query_googleads – Google Ads via google-ads
9
+ β€’ query_sharepoint – SharePoint via Office365-REST-Python-Client
10
+
11
+ Secrets expected in env:
12
+ SF_USER, SF_PASS, SF_TOKEN
13
+ HUBSPOT_TOKEN
14
+ QB_CLIENT_ID, QB_CLIENT_SECRET, QB_REFRESH_TOKEN, QB_REALM_ID
15
+ STRIPE_API_KEY
16
+ GOOGLE_ADS_DEVELOPER_TOKEN, GOOGLE_ADS_LOGIN_CUSTOMER_ID, GOOGLE_ADS_REFRESH_TOKEN, GOOGLE_ADS_CLIENT_ID, GOOGLE_ADS_CLIENT_SECRET
17
+ SHAREPOINT_SITE_URL, SHAREPOINT_CLIENT_ID, SHAREPOINT_CLIENT_SECRET, SHAREPOINT_TENANT_ID
18
  """
19
 
20
+ import os
21
+ import json
22
+ import sqlite3
23
+
24
  from mcp.server.fastmcp import FastMCP
 
 
25
 
26
+ # Salesforce
27
+ from simple_salesforce import Salesforce
28
+
29
+ # HubSpot
30
+ from hubspot import HubSpot
31
+ from hubspot.crm.contacts import ApiException as HSContactsError
32
+
33
+ # QuickBooks
34
+ from quickbooks import QuickBooks
35
+ from quickbooks.objects.customer import Customer # example object
36
+
37
+ # Stripe
38
+ import stripe
39
+
40
+ # Google Ads
41
+ from google.ads.googleads.client import GoogleAdsClient
42
+ from google.ads.googleads.errors import GoogleAdsException
43
+
44
+ # SharePoint
45
+ from office365.runtime.auth.client_credential import ClientCredential
46
+ from office365.sharepoint.client_context import ClientContext
47
+
48
+ # ────────────────────────────────────────────────────────────────────────────
49
  mcp = FastMCP("EnterpriseData")
50
 
51
+ # ─── 1) In-memory SQLite sample ─────────────────────────────────────────────
52
  conn = sqlite3.connect(":memory:", check_same_thread=False)
53
  cur = conn.cursor()
 
54
  cur.execute("""
55
  CREATE TABLE Customers (
56
  CustomerID INTEGER PRIMARY KEY AUTOINCREMENT,
 
71
  )
72
  conn.commit()
73
 
 
74
  @mcp.tool()
75
  def query_database(sql: str) -> str:
76
  """Run SQL against the in-memory Customers table and return JSON rows."""
 
79
  cols = [d[0] for d in cur.description or []]
80
  rows = [dict(zip(cols, r)) for r in cur.fetchall()]
81
  return json.dumps(rows)
82
+ except Exception as e:
83
+ return json.dumps({"error": str(e)})
84
+
85
+ # ─── 2) Salesforce tool ─────────────────────────────────────────────────────
86
+ sf = Salesforce(
87
+ username=os.getenv("SF_USER"),
88
+ password=os.getenv("SF_PASS"),
89
+ security_token=os.getenv("SF_TOKEN"),
90
+ )
91
+
92
+ @mcp.tool()
93
+ def query_salesforce(soql: str) -> str:
94
+ """
95
+ Run SOQL query via simple-salesforce.
96
+ Example: SELECT Id, Name FROM Account WHERE Industry = 'Technology'
97
+ """
98
+ try:
99
+ result = sf.query_all(soql)
100
+ records = result.get("records", [])
101
+ # remove attributes block
102
+ for r in records:
103
+ r.pop("attributes", None)
104
+ return json.dumps(records)
105
+ except Exception as e:
106
+ return json.dumps({"error": str(e)})
107
+
108
+ # ─── 3) HubSpot tool ────────────────────────────────────────────────────────
109
+ hs_client = HubSpot(access_token=os.getenv("HUBSPOT_TOKEN"))
110
+
111
+ @mcp.tool()
112
+ def query_hubspot(object_type: str, limit: int = 100) -> str:
113
+ """
114
+ Fetch up to `limit` objects of type `contacts`, `companies`, or `deals`.
115
+ Example: object_type="contacts"
116
+ """
117
+ try:
118
+ api = getattr(hs_client.crm, object_type)
119
+ page = api.basic_api.get_page(limit=limit)
120
+ items = [r.to_dict() for r in page.results]
121
+ return json.dumps(items)
122
+ except HSContactsError as he:
123
+ return json.dumps({"error": he.body})
124
+ except Exception as e:
125
+ return json.dumps({"error": str(e)})
126
 
127
+ # ─── 4) QuickBooks tool ────────────────────────────────────────────────────
128
+ qb = QuickBooks(
129
+ client_id=os.getenv("QB_CLIENT_ID"),
130
+ client_secret=os.getenv("QB_CLIENT_SECRET"),
131
+ refresh_token=os.getenv("QB_REFRESH_TOKEN"),
132
+ company_id=os.getenv("QB_REALM_ID"),
133
+ )
134
+
135
+ @mcp.tool()
136
+ def query_quickbooks(entity: str, max_results: int = 50) -> str:
137
+ """
138
+ Query QuickBooks Online entity via python-quickbooks.
139
+ entity="Customer" or "Invoice", etc.
140
+ """
141
+ try:
142
+ cls = globals().get(entity, None)
143
+ if cls is None:
144
+ raise ValueError(f"Unknown entity '{entity}'")
145
+ objs = cls.where("", qb=qb, max_results=max_results)
146
+ return json.dumps([o.to_dict() for o in objs])
147
+ except Exception as e:
148
+ return json.dumps({"error": str(e)})
149
+
150
+ # ─── 5) Stripe tool ─────────────────────────────────────────────────────────
151
+ stripe.api_key = os.getenv("STRIPE_API_KEY")
152
+
153
+ @mcp.tool()
154
+ def query_stripe(obj: str, limit: int = 10) -> str:
155
+ """
156
+ List Stripe objects, e.g. obj="customers", "charges", "invoices"
157
+ """
158
+ try:
159
+ method = getattr(stripe, obj)
160
+ items = method.list(limit=limit).data
161
+ return json.dumps([i.to_dict() for i in items])
162
+ except Exception as e:
163
+ return json.dumps({"error": str(e)})
164
+
165
+ # ─── 6) Google Ads tool ────────────────────────────────────────────────────
166
+ ga_config = {
167
+ "developer_token": os.getenv("GOOGLE_ADS_DEVELOPER_TOKEN"),
168
+ "login_customer_id": os.getenv("GOOGLE_ADS_LOGIN_CUSTOMER_ID"),
169
+ "refresh_token": os.getenv("GOOGLE_ADS_REFRESH_TOKEN"),
170
+ "client_id": os.getenv("GOOGLE_ADS_CLIENT_ID"),
171
+ "client_secret": os.getenv("GOOGLE_ADS_CLIENT_SECRET"),
172
+ }
173
+
174
+ ga_client = GoogleAdsClient.load_from_dict(ga_config)
175
 
 
176
  @mcp.tool()
177
+ def query_googleads(customer_id: str, query: str) -> str:
178
  """
179
+ Run a GAQL query against a Google Ads customer.
180
+ Example: query="SELECT campaign.id, campaign.name FROM campaign ORDER BY campaign.id"
 
 
 
181
  """
182
  try:
183
+ service = ga_client.get_service("GoogleAdsService")
184
+ response = service.search(customer_id=customer_id, query=query)
185
+ rows = []
186
+ for row in response:
187
+ # convert protobuf row to dict
188
+ rows.append({k: getattr(row, k) for k in row._pb.DESCRIPTOR.fields_by_name})
189
  return json.dumps(rows)
190
+ except GoogleAdsException as ge:
191
+ return json.dumps({"error": ge.error.message})
192
+ except Exception as e:
193
+ return json.dumps({"error": str(e)})
194
+
195
+ # ─── 7) SharePoint tool ────────────────────────────────────────────────────
196
+ site_url = os.getenv("SHAREPOINT_SITE_URL")
197
+ client_id = os.getenv("SHAREPOINT_CLIENT_ID")
198
+ client_secret = os.getenv("SHAREPOINT_CLIENT_SECRET")
199
+ tenant_id = os.getenv("SHAREPOINT_TENANT_ID")
200
+
201
+ auth_ctx = ClientContext(site_url).with_credentials(
202
+ ClientCredential(client_id, client_secret)
203
+ )
204
+
205
+ @mcp.tool()
206
+ def query_sharepoint(list_title: str, top: int = 50) -> str:
207
+ """
208
+ Fetch items from a SharePoint list.
209
+ Example: list_title="ContactsList"
210
+ """
211
+ try:
212
+ sp_list = auth_ctx.web.lists.get_by_title(list_title)
213
+ items = sp_list.items.top(top).get().execute_query()
214
+ out = [dict(i.properties) for i in items]
215
+ return json.dumps(out, ensure_ascii=False)
216
+ except Exception as e:
217
+ return json.dumps({"error": str(e)})
218
 
219
+ # ─── 8) Start the MCP server ──��────────────────────────────────────────────
220
  if __name__ == "__main__":
221
  mcp.run(transport="stdio")