flock-core 0.5.0b5__py3-none-any.whl → 0.5.0b6__py3-none-any.whl
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.
Potentially problematic release.
This version of flock-core might be problematic. Click here for more details.
- {flock_core-0.5.0b5.dist-info → flock_core-0.5.0b6.dist-info}/METADATA +2 -41
- {flock_core-0.5.0b5.dist-info → flock_core-0.5.0b6.dist-info}/RECORD +5 -15
- flock/tools/__init__.py +0 -0
- flock/tools/azure_tools.py +0 -781
- flock/tools/code_tools.py +0 -167
- flock/tools/file_tools.py +0 -149
- flock/tools/github_tools.py +0 -157
- flock/tools/markdown_tools.py +0 -204
- flock/tools/system_tools.py +0 -9
- flock/tools/text_tools.py +0 -809
- flock/tools/web_tools.py +0 -90
- flock/tools/zendesk_tools.py +0 -147
- {flock_core-0.5.0b5.dist-info → flock_core-0.5.0b6.dist-info}/WHEEL +0 -0
- {flock_core-0.5.0b5.dist-info → flock_core-0.5.0b6.dist-info}/entry_points.txt +0 -0
- {flock_core-0.5.0b5.dist-info → flock_core-0.5.0b6.dist-info}/licenses/LICENSE +0 -0
flock/tools/web_tools.py
DELETED
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
import importlib
|
|
3
|
-
import os
|
|
4
|
-
from typing import Literal
|
|
5
|
-
|
|
6
|
-
from flock.core.logging.trace_and_logged import traced_and_logged
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
@traced_and_logged
|
|
10
|
-
def web_search_tavily(query: str):
|
|
11
|
-
if importlib.util.find_spec("tavily") is not None:
|
|
12
|
-
from tavily import TavilyClient
|
|
13
|
-
|
|
14
|
-
client = TavilyClient(api_key=os.getenv("TAVILY_API_KEY"))
|
|
15
|
-
try:
|
|
16
|
-
response = client.search(query, include_answer=True) # type: ignore
|
|
17
|
-
return response
|
|
18
|
-
except Exception:
|
|
19
|
-
raise
|
|
20
|
-
else:
|
|
21
|
-
raise ImportError(
|
|
22
|
-
"Optional tool dependencies not installed. Install with 'pip install flock-core[tools]'."
|
|
23
|
-
)
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
@traced_and_logged
|
|
27
|
-
def web_search_duckduckgo(
|
|
28
|
-
keywords: str, search_type: Literal["news", "web"] = "web"
|
|
29
|
-
):
|
|
30
|
-
try:
|
|
31
|
-
if importlib.util.find_spec("duckduckgo_search") is not None:
|
|
32
|
-
from duckduckgo_search import DDGS
|
|
33
|
-
|
|
34
|
-
if search_type == "news":
|
|
35
|
-
response = DDGS().news(keywords)
|
|
36
|
-
else:
|
|
37
|
-
response = DDGS().text(keywords)
|
|
38
|
-
|
|
39
|
-
return response
|
|
40
|
-
else:
|
|
41
|
-
raise ImportError(
|
|
42
|
-
"Optional tool dependencies not installed. Install with 'pip install flock-core[tools]'."
|
|
43
|
-
)
|
|
44
|
-
except Exception:
|
|
45
|
-
raise
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
@traced_and_logged
|
|
49
|
-
def web_search_bing(keywords: str):
|
|
50
|
-
try:
|
|
51
|
-
import httpx
|
|
52
|
-
|
|
53
|
-
subscription_key = os.environ["BING_SEARCH_V7_SUBSCRIPTION_KEY"]
|
|
54
|
-
endpoint = "https://api.bing.microsoft.com/v7.0/search"
|
|
55
|
-
|
|
56
|
-
# Query term(s) to search for.
|
|
57
|
-
query = keywords
|
|
58
|
-
|
|
59
|
-
# Construct a request
|
|
60
|
-
mkt = "en-US"
|
|
61
|
-
params = {"q": query, "mkt": mkt}
|
|
62
|
-
headers = {"Ocp-Apim-Subscription-Key": subscription_key}
|
|
63
|
-
|
|
64
|
-
response = httpx.get(endpoint, headers=headers, params=params)
|
|
65
|
-
response.raise_for_status()
|
|
66
|
-
search_results = response.json()
|
|
67
|
-
return search_results["webPages"]
|
|
68
|
-
except Exception:
|
|
69
|
-
raise
|
|
70
|
-
|
|
71
|
-
@traced_and_logged
|
|
72
|
-
def web_content_as_markdown(url: str) -> str:
|
|
73
|
-
if (
|
|
74
|
-
importlib.util.find_spec("httpx") is not None
|
|
75
|
-
and importlib.util.find_spec("markdownify") is not None
|
|
76
|
-
):
|
|
77
|
-
import httpx
|
|
78
|
-
from markdownify import markdownify as md
|
|
79
|
-
|
|
80
|
-
try:
|
|
81
|
-
response = httpx.get(url)
|
|
82
|
-
response.raise_for_status()
|
|
83
|
-
markdown = md(response.text)
|
|
84
|
-
return markdown
|
|
85
|
-
except Exception:
|
|
86
|
-
raise
|
|
87
|
-
else:
|
|
88
|
-
raise ImportError(
|
|
89
|
-
"Optional tool dependencies not installed. Install with 'pip install flock-core[tools]'."
|
|
90
|
-
)
|
flock/tools/zendesk_tools.py
DELETED
|
@@ -1,147 +0,0 @@
|
|
|
1
|
-
"""Tools for interacting with Zendesk."""
|
|
2
|
-
|
|
3
|
-
import os
|
|
4
|
-
|
|
5
|
-
import httpx
|
|
6
|
-
from mcp.server.fastmcp import FastMCP
|
|
7
|
-
|
|
8
|
-
mcp = FastMCP("ZendeskTools")
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
ZENDESK_BEARER_TOKEN = os.getenv("ZENDESK_BEARER_TOKEN")
|
|
12
|
-
|
|
13
|
-
HEADERS = {
|
|
14
|
-
"Authorization": f"Bearer {ZENDESK_BEARER_TOKEN}",
|
|
15
|
-
"Accept": "application/json",
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
@mcp.tool()
|
|
20
|
-
def zendesk_get_tickets(number_of_tickets: int = 10) -> list[dict]:
|
|
21
|
-
"""Get all tickets."""
|
|
22
|
-
ZENDESK_SUBDOMAIN = os.getenv("ZENDESK_SUBDOMAIN_TICKET")
|
|
23
|
-
BASE_URL = f"https://{ZENDESK_SUBDOMAIN}.zendesk.com"
|
|
24
|
-
url = f"{BASE_URL}/api/v2/tickets.json"
|
|
25
|
-
all_tickets = []
|
|
26
|
-
with httpx.Client(headers=HEADERS, timeout=30.0) as client:
|
|
27
|
-
while url and len(all_tickets) < number_of_tickets:
|
|
28
|
-
response = client.get(url)
|
|
29
|
-
response.raise_for_status()
|
|
30
|
-
|
|
31
|
-
data = response.json()
|
|
32
|
-
tickets = data.get("tickets", [])
|
|
33
|
-
all_tickets.extend(tickets)
|
|
34
|
-
|
|
35
|
-
url = data.get("next_page")
|
|
36
|
-
return all_tickets
|
|
37
|
-
|
|
38
|
-
@mcp.tool()
|
|
39
|
-
def zendesk_get_ticket_by_id(ticket_id: str) -> dict:
|
|
40
|
-
"""Get a ticket by ID."""
|
|
41
|
-
ZENDESK_SUBDOMAIN = os.getenv("ZENDESK_SUBDOMAIN_TICKET")
|
|
42
|
-
BASE_URL = f"https://{ZENDESK_SUBDOMAIN}.zendesk.com"
|
|
43
|
-
url = f"{BASE_URL}/api/v2/tickets/{ticket_id}"
|
|
44
|
-
with httpx.Client(headers=HEADERS, timeout=30.0) as client:
|
|
45
|
-
response = client.get(url)
|
|
46
|
-
response.raise_for_status()
|
|
47
|
-
return response.json()["ticket"]
|
|
48
|
-
|
|
49
|
-
@mcp.tool()
|
|
50
|
-
def zendesk_get_comments_by_ticket_id(ticket_id: str) -> list[dict]:
|
|
51
|
-
"""Get all comments for a ticket."""
|
|
52
|
-
ZENDESK_SUBDOMAIN = os.getenv("ZENDESK_SUBDOMAIN_TICKET")
|
|
53
|
-
BASE_URL = f"https://{ZENDESK_SUBDOMAIN}.zendesk.com"
|
|
54
|
-
url = f"{BASE_URL}/api/v2/tickets/{ticket_id}/comments"
|
|
55
|
-
with httpx.Client(headers=HEADERS, timeout=30.0) as client:
|
|
56
|
-
response = client.get(url)
|
|
57
|
-
response.raise_for_status()
|
|
58
|
-
return response.json()["comments"]
|
|
59
|
-
|
|
60
|
-
@mcp.tool()
|
|
61
|
-
def zendesk_get_article_by_id(article_id: str) -> dict:
|
|
62
|
-
"""Get an article by ID."""
|
|
63
|
-
ZENDESK_LOCALE = os.getenv("ZENDESK_ARTICLE_LOCALE")
|
|
64
|
-
ZENDESK_SUBDOMAIN = os.getenv("ZENDESK_SUBDOMAIN_ARTICLE")
|
|
65
|
-
BASE_URL = f"https://{ZENDESK_SUBDOMAIN}.zendesk.com"
|
|
66
|
-
url = (
|
|
67
|
-
f"{BASE_URL}/api/v2/help_center/{ZENDESK_LOCALE}/articles/{article_id}"
|
|
68
|
-
)
|
|
69
|
-
with httpx.Client(headers=HEADERS, timeout=30.0) as client:
|
|
70
|
-
response = client.get(url)
|
|
71
|
-
response.raise_for_status()
|
|
72
|
-
return response.json()["article"]
|
|
73
|
-
|
|
74
|
-
@mcp.tool()
|
|
75
|
-
def zendesk_get_articles() -> list[dict]:
|
|
76
|
-
"""Get all articles."""
|
|
77
|
-
ZENDESK_LOCALE = os.getenv("ZENDESK_ARTICLE_LOCALE")
|
|
78
|
-
ZENDESK_SUBDOMAIN = os.getenv("ZENDESK_SUBDOMAIN_ARTICLE")
|
|
79
|
-
BASE_URL = f"https://{ZENDESK_SUBDOMAIN}.zendesk.com"
|
|
80
|
-
url = f"{BASE_URL}/api/v2/help_center/{ZENDESK_LOCALE}/articles.json"
|
|
81
|
-
with httpx.Client(headers=HEADERS, timeout=30.0) as client:
|
|
82
|
-
response = client.get(url)
|
|
83
|
-
response.raise_for_status()
|
|
84
|
-
return response.json()["articles"]
|
|
85
|
-
|
|
86
|
-
@mcp.tool()
|
|
87
|
-
def zendesk_get_articles_count() -> int:
|
|
88
|
-
"""
|
|
89
|
-
Count every Help-Center article in the configured locale.
|
|
90
|
-
|
|
91
|
-
Uses cursor pagination (page[size]=100) because it’s faster and
|
|
92
|
-
has no 10 000-record ceiling. Falls back to offset pagination
|
|
93
|
-
if the account hasn’t been migrated yet.
|
|
94
|
-
"""
|
|
95
|
-
ZENDESK_LOCALE = os.getenv("ZENDESK_ARTICLE_LOCALE") # e.g. "en-us"
|
|
96
|
-
ZENDESK_SUBDOMAIN = os.getenv("ZENDESK_SUBDOMAIN_ARTICLE")
|
|
97
|
-
BASE_URL = f"https://{ZENDESK_SUBDOMAIN}.zendesk.com"
|
|
98
|
-
url = (
|
|
99
|
-
f"{BASE_URL}/api/v2/help_center/{ZENDESK_LOCALE}/articles.json"
|
|
100
|
-
"?page[size]=100" # max page size for HC APIs
|
|
101
|
-
)
|
|
102
|
-
|
|
103
|
-
total = 0
|
|
104
|
-
with httpx.Client(headers=HEADERS, timeout=30.0) as client:
|
|
105
|
-
while url:
|
|
106
|
-
resp = client.get(url)
|
|
107
|
-
resp.raise_for_status()
|
|
108
|
-
data = resp.json()
|
|
109
|
-
|
|
110
|
-
total += len(data.get("articles", []))
|
|
111
|
-
print(f"Locale: {ZENDESK_LOCALE}")
|
|
112
|
-
print(f"Number of articles: {total}")
|
|
113
|
-
|
|
114
|
-
# Cursor pagination (preferred)
|
|
115
|
-
if data.get("meta", {}).get("has_more"):
|
|
116
|
-
url = data.get("links", {}).get("next")
|
|
117
|
-
continue
|
|
118
|
-
|
|
119
|
-
# Offset pagination fallback
|
|
120
|
-
url = data.get("next_page")
|
|
121
|
-
|
|
122
|
-
return total
|
|
123
|
-
|
|
124
|
-
@mcp.tool()
|
|
125
|
-
def zendesk_search_articles(query: str) -> list[dict]:
|
|
126
|
-
"""Search Zendesk Help Center articles using a query string."""
|
|
127
|
-
ZENDESK_LOCALE = os.getenv("ZENDESK_ARTICLE_LOCALE") # e.g., "en-us"
|
|
128
|
-
ZENDESK_SUBDOMAIN = os.getenv("ZENDESK_SUBDOMAIN_ARTICLE")
|
|
129
|
-
BASE_URL = f"https://{ZENDESK_SUBDOMAIN}.zendesk.com"
|
|
130
|
-
url = f"{BASE_URL}/api/v2/help_center/articles/search.json"
|
|
131
|
-
|
|
132
|
-
params = {
|
|
133
|
-
"query": query,
|
|
134
|
-
"locale": ZENDESK_LOCALE,
|
|
135
|
-
"sort_by": "updated_at",
|
|
136
|
-
"sort_order": "desc",
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
with httpx.Client(headers=HEADERS, timeout=30.0) as client:
|
|
140
|
-
response = client.get(url, params=params)
|
|
141
|
-
response.raise_for_status()
|
|
142
|
-
return response.json().get("results", [])
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
if __name__ == "__main__":
|
|
146
|
-
transport = os.getenv("ZENDESK_MCP_TRANSPORT", "stdio")
|
|
147
|
-
mcp.run(transport=transport)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|